博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
mybatis动态代理
阅读量:4457 次
发布时间:2019-06-08

本文共 2695 字,大约阅读时间需要 8 分钟。

(很早就接触了动态代理,出于不知道这种模式的实用意义到底在哪里,所以每次简单了解完代理的过程不久也忘了。但是知道了mybatis就是利用动态代理来生成mapper实例,借此再总结一次)

JDK动态代理只能针对接口(所以声明Mapper接口),如果要针对普通类则可以考虑CGLib的实现。

 

平时使用mybatis基本都是使用接口声明,然后注入直接调用接口方法,即可完成数据库操作。有没有疑惑过,为什么没看到实现该接口的类,就可以调用方法。要知道接口是不能实例化的。这是对代理类生成(代理模式)的理解。

 

对于常规Java类变量的创建要求有 .java 文件,然后编译成 .class 文件,然后虚拟机加载该 .class 文件,最后才能生成对象。但是对Subject proxyInstance(某个代理实例)该代理类其是不存在 .java 文件的,也就是该对象的 .class 文件是动态生成的,然后虚拟机加载该class文件,然后创建对象。

可知JDK动态代理需要接口,真实实现类,Client调用方。在常规的Mybatis的Mapper代理中接口就是Mapper,Client是service,那么真实的实现类是什么?

这里就是Mapper代理的关键点。

 

从关键的部分开始解读源码:

1、MapperRegistry(Mapper注册器)

MapperRegistry类是注册Mapper接口与获取代理类实例的工具类。
该工具类里头有很明显的执行链:
首先是addMappers(String packageName)方法,该方法通过包名扫描下面所有接口。
该方法内就是对addMappers(重载方法)的调用,该方法只是个中间过程,方法内通过循环执行addMapper(mapperClass)方法。
addMapper对每一个扫描到的接口( if (type.isInterface()) ,接口类也是Class类型,编译后也会生成相应的.class文件 )放进knownMappers
中,knownMappers是一个HashMap,Key是mapper的类型对象, Value是MapperProxyFactory对象。
接着(某处?)调用getMapper方法,方法里面最后会去调用MapperProxyFactory类的newInstance方法。getMapper方法前会初始化
MapperProxyFactory,它是创建Mapper代理对象的工厂。

@SuppressWarnings("unchecked")public 
T getMapper(Class
type, SqlSession sqlSession) { //通过Mapper的接口类型 去Map当中查找 如果为空就抛异常 final MapperProxyFactory
mapperProxyFactory = (MapperProxyFactory
) knownMappers.get(type); if (mapperProxyFactory == null) throw new BindingException("Type " + type + " is not known to the MapperRegistry."); try {    //否则创建一个当前接口的代理对象 并且传入sqlSession return mapperProxyFactory.newInstance(sqlSession); } catch (Exception e) { throw new BindingException("Error getting mapper instance. Cause: " + e, e); }}

 

2、MapperProxyFactory(创建Mapper代理对象的工厂)
该工厂内有两个同名的重载方法,执行链是先通过newInstance(SqlSession sqlSession)方法获得上方所说的真实的实现类mapperProxy,去调用
newInstance(MapperProxy<T> mapperProxy)方法。最后就是一直以来所熟悉的的JDK动态代理return (T) Proxy.newProxyInstance
(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
所以重点回到获得真实的实现类MapperProxy上

 

3、MapperProxy(mapper的实际代理对象)

这个类实现了JDK的动态代理接口InvocationHandler。
该类中有一个methodCache对象,是接口中方法的缓存。
从上方第一点的getMapper方法就是用来获得相关的数据操作类接口。而事实数据操作类邦定了动态代理。所以操据操作类执行方法的时候,会触动
每个方法相应的MapperProxy类的invoke方法。
该方法从缓存中获得MapperMethod实例,通过mapperMethod.execute(sqlSession, args)真正对一个方法执行,可以看出这个方法对才是真正对
SqlSession进行的包装调用。

4、MapperMethod是真正代理一条mybatis mapper标签的方法,要知道动态代理只是对一个方法作代理。
类里面有俩个成员:SqlCommand类和MethodSignature类。一个跟SQL语句有关系,一个跟要执行的方法有关系。
并使用一个内部类SqlCommand来封装底层的增删改查操作,确切来讲这一部分的内容跟XxxMapper的XML配置文件里面的select节点、delete节点等
有关。我们都会知道节点上有id属性值。那么MyBatis框架会把每一个节点(如:select节点、delete节点)生成一个MappedStatement类。要找到
MappedStatement类就必须通过id来获得。

 

参考:

转载于:https://www.cnblogs.com/LinsenLi/p/9609428.html

你可能感兴趣的文章
第2章 安装Nodejs Nodejs基础 课程介绍
查看>>
一维码:EAN-13码的识别
查看>>
office word 2010版本标题编号设置
查看>>
linux命令行模式与图形界面切换
查看>>
XMPP框架下微信项目总结(4)重新连接服务器
查看>>
DCL 语句
查看>>
nodejs 实践:express 最佳实践(八) egg.js 框架的优缺点
查看>>
goldengate 12.2中通过restful查看OGG状态
查看>>
CMS垃圾回收机制
查看>>
SQL Server 常用操作
查看>>
Date, TimeZone, MongoDB, java中date的时区问题
查看>>
liunx一次安装多个软件包
查看>>
python数据类型的转换
查看>>
innerHTML、innerText、outerHTML、textContent的区别
查看>>
Windows下Memcached在.Net程序中的实际运用(从Memcached客户端Enyim的库的编译到实际项目运用)...
查看>>
Adams 2013自定义插件方法zz
查看>>
NSTimer 和 CADisPlayLink 的频露比较
查看>>
ajax
查看>>
触摸屏驱动分析和编程
查看>>
(转)2018移动端网页界面尺寸参考
查看>>