MybatisAutoConfiguration或者MybatisPlusAutoConfiguration核心作用是初始化工厂类SqlSessionFactory,其中包含属性interceptors、MapperLocations、TypeAliasesPackage、TypeEnumsPackage、TypeHandlers等。
MybatisAutoConfiguration自动装配类是由依赖:mybatis-spring-boot-starter【mybatis-spring-boot-autoconfigure】提供的,如果使用Mp版本则直接由MybatisPlusAutoConfiguration替代MybatisAutoConfiguration。
@Mapper通过@Import注解导入ImportBeanDefinitionRegistrar类型的实现类MapperScannerRegistrar
,类ImportBeanDefinitionRegistrar的作用:
- 核心是引入类MapperScannerConfigurer,即初始化其对应的BeanDefinition,并注册至IOC中BeanDefinition类型的注册表中。
- MapperScannerConfigurer实为BeanDefinitionRegistryPostProcessor类型的后置处理器。
- 注解@MapperScan相关属性value重置到MapperScannerConfigurer对应的BeanDefinition内部。
- 将MapperScannerConfigurer对应的BeanDefinition注册至Spring IOC容器内部。
BeanDefinitionRegistryPostProcessor类型的后置处理器MapperScannerConfigurer:此时@Mapper注解相关属性重置于MapperScannerConfigurer。
- 扫描basePackages路径下全部的Mapper接口。
- 遍历每一个接口为其生成BeanDefinition,其内部beanClass属性value为
MapperFactoryBean
。 - 将@Mapper组合注解相关属性转化为MapperFactoryBean相关字段或者方法属性。
@Mapper -> MapperScannerRegistrar -> MapperScannerConfigurer-> MapperFactoryBean转化流程:
public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar{
public void registerBeanDefinitions(AnnotationAttributes annoAttrs,BeanDefinitionRegistry registry, String beanName) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
...
// 将 @MapperScan 属性sqlSessionTemplateRef 作为 MapperScannerConfigurer的属性sqlSessionTemplateRef
String sqlSessionTemplateRef = annoAttrs.getString("sqlSessionTemplateRef");
if (StringUtils.hasText(sqlSessionTemplateRef)) {
builder.addPropertyValue("sqlSessionTemplateBeanName",annoAttrs.getString("sqlSessionTemplateRef"));
}
// 将 @MapperScan 属性sqlSessionFactoryRef 作为 MapperScannerConfigurer的属性sqlSessionFactoryBeanName
String sqlSessionFactoryRef = annoAttrs.getString("sqlSessionFactoryRef");
if (StringUtils.hasText(sqlSessionFactoryRef)) {
builder.addPropertyValue("sqlSessionFactoryBeanName",annoAttrs.getString("sqlSessionFactoryRef"));
}
...
registry.registerBeanDefinition(beanName, builder.getBeanDefinition());
}
}
以上将注解@MapperScan 属性转移到MapperScannerConfigurer。
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean{
private boolean addToConfig = true;
private SqlSessionFactory sqlSessionFactory;
private SqlSessionTemplate sqlSessionTemplate;
private String sqlSessionFactoryBeanName;
private String sqlSessionTemplateBeanName;
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
//以下将 @MapperScan 相关属性转移到 ClassPathMapperScanner
scanner.setAddToConfig(this.addToConfig);
scanner.setAnnotationClass(this.annotationClass);
scanner.setMarkerInterface(this.markerInterface);
scanner.setSqlSessionFactory(this.sqlSessionFactory);
scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
scanner.setResourceLoader(this.applicationContext);
scanner.setBeanNameGenerator(this.nameGenerator);
scanner.setMapperFactoryBeanClass(this.mapperFactoryBeanClass);
scanner.registerFilters();
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage,",; \t\n"));
}
}
将 MapperScannerConfigurer 相关属性转移到类ClassPathMapperScanner。
public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {
private Class<? extends MapperFactoryBean> mapperFactoryBeanClass = MapperFactoryBean.class;
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
GenericBeanDefinition definition;
for (BeanDefinitionHolder holder : beanDefinitions) {//basePackages路径下扫描得到全部Mapper接口
...
// 将 Mapper接口之 GenericBeanDefinition 的BeanClass属性为 MapperFactoryBean
definition.setBeanClass(this.mapperFactoryBeanClass);
// 给 MapperFactoryBean 添加属性字段 addToConfig
definition.getPropertyValues().add("addToConfig", this.addToConfig);
boolean explicitFactoryUsed = false;
// 给 MapperFactoryBean 添加属性字段 sqlSessionFactory
if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
definition.getPropertyValues().add("sqlSessionFactory",new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
explicitFactoryUsed = true;
} else if (this.sqlSessionFactory != null) {
definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
explicitFactoryUsed = true;
}
// 给 MapperFactoryBean 添加属性字段 sqlSessionTemplate
if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
definition.getPropertyValues().add("sqlSessionTemplate",new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
explicitFactoryUsed = true;
} else if (this.sqlSessionTemplate != null) {
definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
explicitFactoryUsed = true;
}
definition.setLazyInit(lazyInitialization);
}
}
}