Mybatis源码分析 - @Mapper 怎么注入到 Spring 容器中?
-
前言
我们在使用spring + mybatis 的时候一般都是用 @MapperScan("包名") 的方式来实现扫描bean并注入到spring 容中。下面让我们好好扒一扒具体的实现方式。
-
流程大纲
- 通过 @MapperScan注解中引入 MapperScannerRegistrar.class 类
- MapperScannerRegistrar类通过实现 ImportBeanDefinitionRegistrar 接口,并重写registerBeanDefinitions方法来将MapperScannerConfigurer类注入到 spring 容器中。
- MapperScannerConfigurer类通过实现BeanDefinitionRegistryPostProcessor接口,重写postProcessBeanDefinitionRegistry 方法,在bean初始化之前进行一些处理。
- 在bean初始化之前使用 ClassPathMapperScanner 的doScan方法来实现扫描指定包名下的所有接口(默认),并添加到spring 容器中提供给后续使用。
- 在第4步的时候扫描到所有的接口后,接口是没有办法注入到spring容器中的,实际注入的是MapperFactoryBean类,在spring注入之前会调用checkDaoConfig()方法来验证配置同时会将Mapper接口添加到mybatis的Configuration中。
- 在spring注入的时候会调用MapperFactoryBean类的getObject()方法,这个方法里面就是sqlSessionTemplate.getMapper()方法了,这样就会返回一个mybatis自己动态代理生成的mapper类提供给spring容器了。
-
涉及知识点
其实这里很多知识点都是spring的知识点,很多第三方组件继承spring使用的方式都同理。下面加粗的类便是需要重点阅读的类。
-
MapperScan.class 中用到了
@Import(MapperScannerRegistrar.class) -
MapperScannerRegistrar.class 中实现了
ImportBeanDefinitionRegistrar -
MapperScannerConfigurer.class 中实现了
BeanDefinitionRegistryPostProcessor -
MapperScannerConfigurer.postProcessBeanDefinitionRegistry()方法中用到了
ClassPathMapperScanner -
扫描Mapper文件注入
MapperFactoryBean后,通过getObject()方法获取到mybatis代理类。
-