1 前言
这节我们看个源码相关的东西,就是我们平时写的 Mapper 接口是怎么注入到 Spring 中呢?
我们会去想:
比如Mapper接口在启动时是如何被发现的?
Mapper接口我们知道肯定是会创建代理的,那么代理对象又是如何创建的呢?
我们接下来就来看看。
2 @Mapper引发的效应
在SpringBoot与Mybatis整合的过程中,往往都会在启动类上标注 @MapperScan注解,并指定basePackage。
那我们跟进去这个注解进去瞅瞅,会发现一个 @Import ,可以看到引入的是类 MapperScannerRegistrar。
那我们进入这个类看看:
ConfigurationClassPostProcessor
解析,如果发现@Import引入的是一个 ImportBeanDefinitionRegistrar 的实现,则会立即调用其 registerBeanDefinitions
方法。那我们继续看:可以看到王我们的容器里注入的一个Bean的描述文件,并且类型是 MapperScannerConfigurer,那我们来看看这个类结构:
可以看到的就是 BeanDefinitionRegistryPostProcessor ,这不是我们熟悉的一个后置处理器么,我们Debug看看:
就会执行到 MapperScannerConfigurer里的 postProcessBeanDefinitionRegistry 方法啦:
然后我们进入 Scan方法,这里要注意的是 doScan实际调用的是 mybatis-spring中的 ClassPathMapper 里的方法哈,这个很关键哈:
我们进入到doScan中来看看,对我们的BeanDefinition进行了转换,变成了MapperFactoryBean,并且设置了 SqlSessionTemplate、SqlSessionFactory等属性。
到这里我们的 Mapper接口的Bean描述文件就放进了 Spring容器了,并且Bean类型是 MapperFactoryBean包装起来的。
3 MapperFactoryBean
那我们对象怎么创建的呢,我们来看看:
通过Bean的描述文件获取Bean对象,就是执行MapperFactoryBean的getObject 方法,继而通过 SqlSession来进行代理对象的创建。
4 涉及到的关键组件
- @MapperScan 配置扫描包并引入MapperScannerRegistrar
- MapperScannerRegistrar 扫描Mapper接口以及增强MapperFactoryBean创建代理对象的埋入
- ImportBeanDefinitionRegistrar Bean描述文件放进Spring容器
- ClassPathBeanDefinitionScanner ClassPathMapperScanner 扫描增强
5 小结
好啦,本节我们主要看了一下 Mapper接口是怎么和 Spring融合的哈,有理解不对的地方欢迎指正哈。