最近想研究研究Mybatis源码,了解一下Mybatis的执行过程,从mybatis-config.xml配置文件开始,一直到Mybatis执行CRUD位置,中途出现很多疑惑,今天特记录一个!
Mybatis在执行CRUD前,会读取咱们的Mapper接口层,即Dao层,但我们写的时候只写了接口,缺没有写实现类,Mybatis是如何执行的呢,首先想到了动态代理,果不其然被我找到了:
public class MapperProxyFactory<T> {
private final Class<T> mapperInterface;
private final Map<Method, MapperMethodInvoker> methodCache = new ConcurrentHashMap<>();
public MapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public Class<T> getMapperInterface() {
return mapperInterface;
}
public Map<Method, MapperMethodInvoker> getMethodCache() {
return methodCache;
}
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
//就是在这里,使用了Proxy对象来生成代理类实体的
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
//这个是代理类实体对象的调用处理器,继承InvocationHandler
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
}
那么疑惑来了,生成的代理对象是什么样子的呢,文件又在哪呢?
其实吧,JDK动态代理实在JVM运行过程中生成代理对象的,所以当JVM没有运行时,是没有代理对象的,那么如何让其生成文件呢?介绍几个方法:
最方便最简单最直观的方式:`saveGeneratedFiles``,此方法只针对jdk动态代理
1. 在代码的启动入口(Main)加入如下代码,二选一:
//JDK1.8及以前的版本
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
//JDK1.8以后的版本
System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");
如图所示:
2. 运行main方法
这就省了,要是这都不会,可以考虑改行了,哈哈哈
3. 寻找文件
项目根路径的同级目录,我的项目名称为bigdata
,如图所示:
注意:生成的路径一般为com\sun\proxy$Prroxy**.class
4. 查看生成的文件
简单粗暴,直接将class文件拖拽到IDEA中,如下:
画个重点:
麻烦点,使用JVM工具:HSDB,此工具既可以查看jdk生成的动态代理对象,也可以查看cglib生成的动态代理对象!
1. 获取PID
jps
获取PID,我的PID为:16872PS C:\dev_workspace\other\stu> jps
18944 Launcher
21392 RemoteMavenServer36
27664 Launcher
19508 Jps
24116
17508 JUnitStarter
18216
PS C:\dev_workspace\other\stu>
2. 执行命令,获取HSDB(HostSpot Debugger)工具:
java -classpath "%JAVA_HOME%/lib/sa-jdi.jar" sun.jvm.hotspot.HSDB
点击此链接后将会生成代理对象,位置在C盘中,个人用户下的com文件夹下, 如:
6.查看生成的代理对象
继续暴力拖拽至IDEA中
图略。。。
感觉是最麻烦的一种:IO流,通过代码使用IO的方式,将代理对象以流的方式写入文件中,感觉太麻烦了,偷个懒,略了略了。。。