啃了一周tkmybatis源码,51张图,5个主要流程,构成了tkmybatis的源码组成 。tkmybatis包括了mybatis的部分,源码相比于mybatis多了个mApperscan的注解处理,其余部分是一致的 。理清了tkmybatis,就理清了mybatis源码,同时对mybatis的机制能有更深刻的认识 。
纯mybatis每个持久化操作都要写sql,会显得有些繁琐 。现在市面上也有很多的插件,比如mybatis逆向工程,mybatisCodeHelperPro等,可以在xml文件中生成一些常用的sql和对应的mapper接口方法 。也有一些mybatis的第三方工具框架,帮我们免去单表操作的sql编写,比如tkmybatis 。tkmybatis源码版本:
<dependency><groupId>tk.mybatis</groupId><artifactId>mapper-spring-boot-starter</artifactId><version>2.1.5</version></dependency>一、tkmybatis使用案例
mybatis系列-5分钟教你提升CRUD开发效率200%
二、整体流程
tkmybatis流程大概分为以下几步:
- 根据properties文件中配置的xml位置,为每个mapper接口生成一个MappedStatement对象(此时对象的SQLSource为不可执行的Provider)
- 根据ScanMapper接口, 将接口加入到Spring 容器中,创建对应的BeanDefinition,然后修改BeanDefinition中的Bean类型为MapperFactoryBean
- Spring容器实例化MapperFactoryBean实例,在初始化方法中,获取第一步每个接口生成的MappedStatement对象,并将MappedStatement对象的SQLSource修改为可执行的SqlSource(Provider生成xml格式的SQL,根据该SQL利用languageDriver创建新的sqlSource)
- 将mapper的bean实例注入到需要依赖该实例的service中,此时会Spring容器调用MapperFactoryBean的getObject方法,该方法创建了一个mapper的代理类(使用jdk的动态代理方法),并注入到service里面去
- 执行SQL时,对mapper的SQL操作,都由mapper的代理类mapperProxy来实现,实现过程跟原生mybatis用sqlsession创建的代理类一样的,只是这里没有显示的使用sqlsession来创建代理类,而是放到了MapperFactoryBean的getObject里面,将生成的代理类注入给service
入口@MapperScan

文章插图
这个注解会@Import进来一个tk.mapper的扫描器(将MapperScannerRegistrar导入到到Spring容器中,并将其声明成一个bean,该类的功能是处理注解MapperScan,具体过程见后面)

文章插图
MapperScannerRegistrar实现了spring的
ImportBeanDefinitionRegistrar接口, 并实现了registerBeanDefinitions方法 。【注:如下图Spring容器在初始化的时候,会先扫描基本注解如controller等,然后扫描第三方jar包中的组件,扫描完成后再找到实现了
ImportBeanDefinitionRegistrar接口的Bean,并将当前的AnnotationMetadata和BeanDefinitionRegistry作为参数传入,通过该Bean扫描自定义注解的组件进来】

文章插图
该bean在实例化的时候,会调用registerBeanDefinitions方法来扫描并导入mapper接口,接着来看下扫描过程 。

文章插图
b、创建扫描器并利用MapperScan参数初始化该扫描器
该步骤创建一个扫描器, 利用MapperScan参数初始化该扫描器,各参数意义后面说,默认为空也没关系 。同时还会根据MapperScan参数确定扫描package的范围 。

文章插图

文章插图
c、注册扫描器filter之所以把这个单独提出来,是因为这一步决定了scanner能扫描出哪些mapper,符合filter条件的就会被扫描出来 。

文章插图
看下registerFilters的具体实现:在registerFilters中,扫描器会添加includeFilter和excludeFilter,如果扫描出来的类在某一个excludeFilter中,则放弃该类,如果扫描出来的类在某一个includeFilter中,则保存该类到扫描的返回结果中,excludeFilter要先于includeFilter进行判断 。详见(
ClassPathScanningCandidateComponentProvider的isCandidateComponent方法) 。
下图中annotationClass和markerInterface都是在前面初始化扫描器的时候,通过MapperScan注解传入的 。
推荐阅读
- 病毒都去哪了,为什么现在的电脑很少中毒
- 我也没想到,Java开发 API接口可以不用写 Controller了
- 许褚被张飞刺于马下视频,为何许褚却平不了张飞
- 李重茂当了多久的皇帝,李重茂与李隆基的关系
- 关羽败走麦城是输给了谁,关羽败走麦城输给了哪位武将
- 汉献帝刘协是一个怎样的人,汉献帝知道刘备称帝了吗
- 三国最后被谁统治了,三国最后被谁统治了
- Java中的封装、继承和多态,你真的都懂了吗
- 详读!别再说不知道增值电信业务许可证是什么了
- 什么茶叶喝了可以减肥,喝什么茶减肥快又健康
