亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字( 三 )


mybatis-spring-boot-starter的依赖包中的mybatis-spring-boot-autoconfigure:

亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字

文章插图
 
查看该jar包
mapper-spring-boot-autoconfigure-2.1.5.jar,可以发现在META-INF下有个spring.factories文件 。
亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字

文章插图
 
该配置利用Spring的组件扫描机制,配置了Spring加载jar包后需要扫描的jar包内的配置类 。该机制可以参考《004-JAVA基础-02-Spring类SPI机制,如何将jar包中的类加载到BeanFactory中进行管理》 。文件内容如下:
亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字

文章插图
 
我们看下这个类,这个类被Spring加载进来后会做很多事情:
亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字

文章插图
 
创建SqlSessionFactory的Bean:
亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字

文章插图
 
创建SqlSessionTemplate的Bean:
亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字

文章插图
 
到这里,MapperFactoryBean的关键属性的注入讲完了 。
b、SqlSessionFactory初始化操作内容
前面讲到MapperFactoryBean自动注入了SqlSessionFactory的Bean,为了讲清楚MapperFactoryBean在属性注入后执行的checkDaoConfig操作,我们先了解下SqlSessionFactory初始化的时候都做了什么事情 。tkmybatis中SqlSessionFactory的初始化基本就是调用mybatis的初始化过程 。简要概括为以下几点:
  • 读取Properties配置文件,提取mybatis相关配置
  • 解析xml文件,将xml文件mapper节点中的mapper类解析并存放到mapperRegistr中,作为knowsmapper
  • 根据mapper的接口方法,为每一个方法创建一个对应的mappedStatement(敲黑板,checkDaoConfig操作主要就是为了调整它),创建mappedStatement时会解析mapper中的method方法,创建对应的SqlSource(根据注解类型判断,如果是insert等基本注解,则利用LanguageDriver和注解上的SQL语句来创建SqlSource,如果是Provider等注解,tkMybatis就是这一类,则创建的SqlSource为ProviderSqlSource)
下面从源码里面看下这几部分:
亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字

文章插图
 
factory.getObject()方法跟下去,发现接着会用加载配置的xml文件,生成Resource列表,然后遍历处理列表中的Resource
亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字

文章插图
 
xmlMapperBuilder.parse()方法跟下去,发现是调用了Mybatis中Configuration的addMapper方法(实现中又是直接调用的MapperRegistry的addMapper方法),处理每一个mapper类,将其添加到mapper注册中心 。
亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字

文章插图
 

亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字

文章插图
 
再进一步,看addMapper方法是如何处理mapper类,注意这里knownMappers.put方法很重要,knowMappers中保存了根据xml配置获取到的所有的mapper类,这里在put的时候,将mapper类转换成了对应的代理类工厂MapperProxyFactory(MapperFactoryBean在完成初始化后,如果在其他类中需要注入MapperFactoryBean的实例,会由Spring容器调用它的getObject方法创建并注入进去 。在getObject方法里会调用代理工厂类的实例方法,会利用jdk的动态代理技术为mapper类实例创建对应的代理类实例,返回给MapperProxyFactory的getObject方法,随后MapperProxyFactory将该代理类实例作为mapper类的实例(比如UserMapper的实例userMapper,实际就是Mapper的代理类实例),执行sql的时候,实际SQL调用都是在MapperProxy的invoke方法中进行处理的)
亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字

文章插图
 

亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字

文章插图
 
在parse()方法中,做如下操作:
亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字

文章插图
 
parseStatement方法完成MappedStatement创建,包括根据方法注解创建SqlSource,然后利用SqlSource创建MappedStatement 。
亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字

文章插图
 

亲自啃了一周,终于把Mybatis源码理清,以后简历请写精通二字

文章插图
 
getSqlSource方法会根据mapper方法上的注解类型,决定返回何种SqlSource 。


推荐阅读