MyBatis源码分析篇----org.apache.ibatis.session.SqlSession#getMapper的源码分析
源起
- 上节我们了解了诸如:
session.selectOne
、session.selectList
等方法的源码实现; - 比如:我们可以查看
mybatis-3.5.4
源码测试包中org.apache.ibatis.session.SqlSessionTest#shouldSelectOneAuthor
,这个方法: - 上图中,框选出的
statement
是以硬编码的方式存在在代码中的,对于后台人员来讲,这部分的编码是不易维护的,所以,MyBatis
封装了Mapper
,通过初始化加载,将所有的Mapper
文件与SQL
文件建立一一对应关系,而在调用的时候使用API
调用方式,直接调用。 - 所以我们可以首先获取到
Mapper
映射器,然后调用其方法执行查询即可,这也是我们最常用的方式;可参考源码包中测试方法org.apache.ibatis.session.SqlSessionTest#shouldSelectAuthorsUsingMapperClass
源码分析
- 首先我们需要获取到
SqlSession
,这个已经在上篇源码分析中已做讲解;需要的可参考
DefaultSqlSession#getMapper
- 首先调用
org.apache.ibatis.session.defaults.DefaultSqlSession#getMapper
方法获取一个映射器代理类;(可以理解为使我们写的dao
接口,只不过是被代理过的,下面会详细讲到)
-
org.apache.ibatis.session.Configuration
中保存了全局配置信息;
MapperRegistry#getMapper
-
protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
是Configuration
的一个属性,它内部维护了一个private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();
用以存储已经存在的Mapper
映射信息;这个操作是在初始化配置信息中就已经加载了,这个我们在之前的源码分析中已分析,可参考:源码分析篇全局配置文件初始化; - 当我们的程序一启动,这个
knownMappers
就已经被初始化了,且knownMappers
的key=xxx.Class
,Value
是一个代理类工厂MapperProxyFactory
,最后可通过mapperProxyFactory.newInstance(sqlSession)
获取代理类MapperProxy
,通过这里,我们可以看出,因为用的是代理类,所以我们的Mapper接口不需要实现类;
JDK
动态代理生成代理类
- 获取接口代理类的方式采用的是
JDK
的动态代理生成代理类; -
mapperProxyFactory.newInstance(sqlSession)
获取代理类MapperProxy
MapperProxy#invoke
- 通过
org.apache.ibatis.session.defaults.DefaultSqlSession#getMapper
获取到了Mapper
的代理类MapperProxy
, - 接下来调用
Mapper
中定义的方法,则必然执行的是代理类的invoke
方法;
-
PlainMethodInvoker
是MapperProxy
的一个静态内部类,cachedInvoker
返回PlainMethodInvoker
,再调用invoke执行方法
new MapperMethod
-
cachedInvoker
方法中new PlainMethodInvoker
传递了一个MapperMethod
,MapperMethod
中有两个静态内部类;如下图所示:
-
SqlCommand
中维护了SQL
的操作命令,包含nameSpace
+节点ID值、需要执行SQL
的类型(INSERT|DELETE|UPDATE|SELECT
) -
MethodSignature
维护方法签名,保存了当前需要执行方法的返回值类型,参数名称解析器等信息;
MapperMethod#execute
- 综上,我们已经获取到了,
SQL
执行相关的信息,接下来,我们看下具体的执行; - 不论
invoke
方法中走哪段逻辑,最后都会调用到execute
方法中执行 - 这里不论增删改查哪种方法,最终都会调用到
SqlSession
中的增删改查方法。 - 对于
SqlSession
中的查询方法执行流程,可参考上篇博文;SqlSession#select
时序图
公众号推荐
微信公众号:从demo到折腾源码
微信号:albert_ztym