初衷
最近想研究研究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中,如下:
画个重点:
- 查清楚自己的JDK版本,不然再怎么操作也看不到!!!
- Main方法中,Test的Junit单元测试中不会出现,不用试了,我就是调到这个坑了!!!
- 文件位置为跟目录的同级目录!!!
方法二
麻烦点,使用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
3. 将PID填入HSDB工具
填入后:
4.获取代理对象
- 查看代理对象地址,可以看到此处为
Proxy24@3339
- 使用HSDB搜索此对象
5. 生成代理对象
点击此链接后将会生成代理对象,位置在C盘中,个人用户下的com文件夹下, 如:
6.查看生成的代理对象
继续暴力拖拽至IDEA中
图略。。。
方法三
感觉是最麻烦的一种:IO流,通过代码使用IO的方式,将代理对象以流的方式写入文件中,感觉太麻烦了,偷个懒,略了略了。。。