mapper是比较神奇的东西,通过一个接口,不写实现类,就可以完成sql语句的执行。
通过对jdk的动态代理进行学习,开始明白了其中的原理。
一个demo:
文件1:Subject.java 对应的就是XxMapper.java
public interface Subject { void hello(String name); }
文件2:SubjectProxy.java 对应的就是 MapperProxy.java
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class SubjectProxy implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("hello world " + args[0]); // System.out.println(method.getDeclaringClass().getName()+"."+method.getName()); return null; } }
文件3:Client.java 对应的就是 平时使用XxMapper接口的地方
import java.lang.reflect.Proxy; public class Client { public static void main(String[] args) { SubjectProxy proxy = new SubjectProxy(); Subject sub = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(), new Class[]{Subject.class}, proxy); sub.hello("kitty"); } }
执行结果:
---------------------------------------------------------------------
再SpringBoot中,Spring框架会自动生成Mapper的代理,是MapperProxy<T>的实例,
其中的invoke方法会拦截,对mapper.方法的调用。
然后会执行关键代码:
MapperMethod mapperMethod = this.cachedMapperMethod(method);
return mapperMethod.execute(this.sqlSession, args);
因为Mapper接口的包名,和XxMapper.xml的命名空间一致,
Mapper接口中的方法名称又和,XxMapper.xml中的sql的id一致,
在MapperProxy中,又会把调用mapper接口的参数也拿到;
于是在MapperMethod实例中,其实就是通过sqlSession对,数据库进行操作了。用到的是命令模式。
---------------------------------------------------------------------
大概也就是这个样子了,原来最终Mapper接口都没有实例。对动态代理也有一点点失望,失望来自于误解,
还以为会自动,的生成Mapper的实现,谁知只是张冠李戴。