SpringBoot 集成 Mybatis 启动流程与原理

       最近一直处于疯狂读源码的状态,简直就是少壮不努力,老大徒伤悲。言归正传,虽然所在的公司用的框架都是内部的,基于开源的框架封装的,但是平时自己写东西的时候,还是喜欢直接用开源的框架。在大学的时候就用过SpringBoot,工作以后也用过Mybatis,但是会用却不是很了解原理。最近就很好奇,SpringBoot的项目通过starter的形式集成Mybatis后,启动的流程与原理,于是就好好的梳理了一下。

      看之前,首先需要了解下SpringBoot的启动流程,推荐下面的原创博客,看了以后,对SpringBoot的启动流程了解了大概,不然笔者也是云里雾里的:

https://www.cnblogs.com/hello-shf/p/10976646.html

    看完以后,开始介绍SpringBoot 集成 Mybatis 启动流程与原理

    首先,先介绍下笔者的示例项目的信息:

  •      springBoot版本:2.2.0.RELEASE
  •      mybatis版本:3.5.2

    通过starter引入

<dependency>

    <groupId>org.mybatis.spring.boot</groupId>

    <artifactId>mybatis-spring-boot-starter</artifactId>

    <version>2.1.0</version>

</dependency>

  项目中,只有一个Mapper接口,如下,只有一个查询接口。

启动类上,没有关于Mybatis的注解,也没有自定义的Mybatis的配置类,配置文件中也没有特殊的配置。接下来开始描述流程:

另外说明:最近想把项目用开源的框架再撸一遍,因此一些内容可能是公司项目的命名,因此都马赛克了,以后有空换个简单的项目把截图再替换下吧。

1. Mybatis starter 通过SPI扩展机制实现的自动装配

找到对应的Spring.factories

spring.factories的配置如下:

# Auto Configure

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\

org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration,\

org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

具体看MybatisAutoConfiguration这个配置类

2. 实例化sqlSessionFactorysqlSessionTemplate

其实大家都知道 对应Mapper的接口,实现原理其实是代理,但是具体流程是怎么实现的呢

3.在Springboot启动,刷新应用上下文时,即执行SpringApplication的refreshContext方法

请锁定PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法中的这段代码

查看变量postProcessorNames的内容

存在MapperScannerConfigurer

查看MapperScannerConfigurer类,一开始很疑惑,因为在这个类上并没有@Component注解。那是怎么注册到BeanDefinition中的呢,后来发现了如下代码,将MapperScannerConfigurer注册到BeanDefinition中:

言归正传,来看看如何实现扫描的

4.注解扫描

因为MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor接口,因此在refresh时,会调用postProcessBeanDefinitionRegistry方法。

一步步往里看,到ClassPathBeanDefinitionScanner类中doScan方法,findCandidateComponents是去扫描指定的包中@Mapper的接口。

从这里可以看出,已经搜索到@Mapper注解的接口了。

但是看这个definitionHolder,总觉得有点奇怪

ClassPathMapperScanner类中,扫描完,beanDefinitions中存放着扫描到的所有的mapper的接口,然后执行processBeanDefinitions方法。

在processBeanDefinitions方法中,会对刚刚的beanDefinition进行进一步加工,这也解决了我之前的疑惑。

再看看beandefinition

5.如何实例化代理类

由于实例化容器是一大堆关于spring的逻辑,因此粗粗略过。

看DefaultListableBeanFactory的resolveDependency方法,顾名思义,应该是解决依赖的方法,因为serviceImpl类中,成员变量xxxDao是以autowrie的形式注入进来的,因此需要实例化xxxDao进行注入。

跟着代码一步步追进去,就能发现AbstractBeanFactory的doGetBean中,以下方法,getSingleton,会先判断该单例的bean是否已经被创建,如果没有,则创建

最终会调用MapperFacctoryBean的getObject方法中,获取代理类

这样在使用的时候,获取的便是代理类。

另外,当多个xxxServiceImpl依赖同一个@Mapper注解的接口时,如果该接口已经实例化过后,便可以从以下方法中获取之前实例化的bean,且代理类是同一个对象。

在第一次创建时,便会将实例的对象放在factoryBeanObjectCache中。

  最后

      追了上面的代码以后,也算大致了解许多SpringBoot的Starter是怎么集成的,融会贯通。

       另外之前读过一些Spring的书籍,也算用了很久的Spring框架了,但是一直没有深究过源码,偶尔看看别人的博客,但是这次感觉纸上得来终觉浅,还是得追着代码看下,感觉对Spring框架还是很不熟悉,而且读源码的确是很枯燥,最近有点心血来潮,但还是希望以后能一点一滴,慢慢积累。

发布了5 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_20614905/article/details/102862189