
文章插图
到这里mapper解析的操作就完成了,MapperFactoryBean中的configuration保存了每一个mapper方法的mappedStatement以及已知的mapper类 。
c、为每个方法对应的MappedStatement更新SqlSource
我们再回到MapperFactoryBean类,来看看它的checkDaoConfig方法都做了些什么 。先把结论说了吧,checkDaoConfig会根据mapper接口将每个接口方法对应的sqlSource,由前面说的ProviderSqlSource转换成languageDriver创建的sqlSource(可以理解为tkMybatis根据每个方法的定义,利用Provider为每个方法在对应的mapper.xml中添加了方法对应的SQL语句,然后利用修改后的xml创建新的sqlSource,更新到MappedStatement里面去,只有更新后的MappedStatement,才能执行Mybatis的SQL处理 。当然实际上是没有直接修改xml文件这一步的,只是打个比方,可以看后面的代码实现) 。

文章插图
再继续看processConfiguration方法做了什么操作 。

文章插图
再继续看processMappedStatement对MappedStatement的处理,该处理中会对MappedStatement中的SqlSource进行替换 。

文章插图
看一下替换前,MappedStatement中的SqlSource如下图所示,是个Provider实现类 。

文章插图
执行setSqlSource后,在下图中可以看见,MappedStatement中的sqlSource参数已经变成了DynamicSqlSource 。

文章插图
接下来,我们继续看下setSqlSource到底是怎么改变sqlSource的 。

文章插图
继续看mapperTemplate的setSqlSource方法,该方法完成了xml形式sql的创建和对应sqlSource的创建 。

文章插图
跟进method.invoke方法,可以发现,该方法实际是在mapper接口方法对应的Provider实现类中执行的,如下图selectByExample方法由ExampleProvider来生成xmlsql 。

文章插图
至此,tkMybatis就在checkDaoConfig方法中将接口方法对应的MappedStatement中的sqlSource由不能执行的Provider实现类,转换成了Mybatis中的可执行的sqlSource(根据xmlSql生成,和mybatis扫描mapper.xml文件中创建的MapperStatement和SqlSource具有同样的功效!)
到目前为止,经过1、Mapper接口扫描和2、Mapper 接口Bean的实例化就完成了tkMybatis的初始化工作 。
3、将Mapper实例注入到依赖该实例的bean中
前面tkMybatis做了两件事情,一是扫描Mapper接口比如UserMapper,创建对应的Bean定义,并将其中的类型修改为MapperFactoryBean;二是实例化该Bean,因为类型已经修改为MapperFactoryBean,就完成MapperFactoryBean的实例化和初始化 。
接下来还有关键的一步,怎么用这个Bean,我们在写service的时候,会通过@autowired注解将Mapper注入到service中,比如下面的:

文章插图
以UsersMapper举个例子,Spring在注入UsersMapper时,会调用对应MapperFactoryBean实例的getObject方法,如下图,在该方法中,会创建UsersMapper的的代理类,进入getmapper这个方法,会跟到前面第2部分knowMappers部分,getmapper是从knowMappers获取的Mapper,该Mapper是一个Mapper接口的代理类MapperProxy,对UserMapper的方法调用都会有MapperProxy的invoke方法来实现 。
这也就解决了“明明是Mapper的接口比如UserMapper,但是在bean定义中把它的类型改成了MapperFactoryBean,MapperFactoryBean又没有实现Mapper的接口方法,那么service中注入的mapper调用方法的时候是如何调用的问题” 。

文章插图
4、实际SQL语句的执行
接着上一部分,调试下实际执行SQL语句的过程 。

文章插图

文章插图
其实,像下图一样,使用经过注入后的Mapper代理类,就跟原生Mybatis创建的代理类是一样的,执行的SQL操作的过程也是一样的 。里面的每个接口方法也都有对应的MappedStatement实现 。如果对invoke代理的过程感兴趣,可以调试跟进去看,看看如何invoke中如何用MappedStatement做具体的SQL处理,这里就不具体说了 。
推荐阅读
- 病毒都去哪了,为什么现在的电脑很少中毒
- 我也没想到,Java开发 API接口可以不用写 Controller了
- 许褚被张飞刺于马下视频,为何许褚却平不了张飞
- 李重茂当了多久的皇帝,李重茂与李隆基的关系
- 关羽败走麦城是输给了谁,关羽败走麦城输给了哪位武将
- 汉献帝刘协是一个怎样的人,汉献帝知道刘备称帝了吗
- 三国最后被谁统治了,三国最后被谁统治了
- Java中的封装、继承和多态,你真的都懂了吗
- 详读!别再说不知道增值电信业务许可证是什么了
- 什么茶叶喝了可以减肥,喝什么茶减肥快又健康
