大家好,又见面了,我是你们的朋友全栈君。
@MapperScan
代码语言:javascript复制@MapperScan({"com.kq.mybatis.mapper","com.kq.mybatis1.mapper"})
代码语言:javascript复制public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AnnotationAttributes mapperScanAttrs = AnnotationAttributes
.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
if (mapperScanAttrs != null) {
registerBeanDefinitions(mapperScanAttrs, registry, generateBaseBeanName(importingClassMetadata, 0));
}
}
这样是默认扫描com.kq.mybatis.mapper和com.kq.mybatis1.mapper包下的所有.clsss文件,而不是扫描这2个包下的所有Mapper文件
@MapperScan指定markerInterface
这里通过@MapperScan指定markerInterface,这样扫描出来的都是实现该接口的Mapper
代码语言:javascript复制@MapperScan(value = {"com.kq.scan.mybatis.mapper","com.kq.scan.mybatis1.mapper"},markerInterface = MybatisBaseMapper.class)
public interface AccountMapper extends MybatisBaseMapper { }
这个markerInterface 最终设置的是MapperScannerConfigurer的 markerInterface属性
@MapperScan指定annotationClass
代码语言:javascript复制@MapperScan(value = {"com.kq.scan.mybatis.mapper","com.kq.scan.mybatis1.mapper"},markerInterface = MybatisBaseMapper.class,annotationClass=Mapper.class)
@Mapper
public interface UserMapper { }
这个annotationClass最终设置的是MapperScannerConfigurer的 annotationClass属性
注意:
@MapperScan同时指定markerInterface 和 annotationClass 两个元素的时候,只要1个条件满足,就算符合条件,而不是要两个条件都满足
MapperScannerRegistrar
代码语言:javascript复制BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
builder.addPropertyValue("processPropertyPlaceHolders", true);
Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
if (!Annotation.class.equals(annotationClass)) {
builder.addPropertyValue("annotationClass", annotationClass);
}
// 看这里 markerInterface
Class<?> markerInterface = annoAttrs.getClass("markerInterface");
if (!Class.class.equals(markerInterface)) {
builder.addPropertyValue("markerInterface", markerInterface);
}
@MapperScans
代码语言:javascript复制@MapperScans({@MapperScan("com.kq.mybatis.mapper"),@MapperScan("com.kq.mybatis1.mapper")})
代码语言:javascript复制static class RepeatingRegistrar extends MapperScannerRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AnnotationAttributes mapperScansAttrs = AnnotationAttributes
.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScans.class.getName()));
if (mapperScansAttrs != null) {
AnnotationAttributes[] annotations = mapperScansAttrs.getAnnotationArray("value");
for (int i = 0; i < annotations.length; i ) {
registerBeanDefinitions(annotations[i], registry, generateBaseBeanName(importingClassMetadata, i));
}
}
}
}
使用@MapperScans,spring的bean定义,注册的MapperScannerRegistrar 有多个的,看上图
注意
每个@MapperScan最终都会初始化1个MapperScannerConfigurer,主要关键的属性basePackage、annotationClass、markerInterface
主要相关类
代码语言:javascript复制org.mybatis.spring.annotation.MapperScannerRegistrar
org.mybatis.spring.mapper.MapperScannerConfigurer
类图
总结
@MapperScan主要就是扫描得到mybatis的Mapper,并最终在Spring容器种初始化
未配置@MapperScan
代码语言:javascript复制org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
代码语言:javascript复制/**
* If mapper registering configuration or mapper scanning configuration not present, this configuration allow to scan
* mappers based on the same component-scanning path as Spring Boot itself.
*/
@org.springframework.context.annotation.Configuration
@Import(AutoConfiguredMapperScannerRegistrar.class)
@ConditionalOnMissingBean({ MapperFactoryBean.class, MapperScannerConfigurer.class })
public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean {
@Override
public void afterPropertiesSet() {
logger.debug(
"Not found configuration for registering mapper bean using @MapperScan, MapperFactoryBean and MapperScannerConfigurer.");
}
}
重点看下面这句话
If mapper registering configuration or mapper scanning configuration not present, this configuration allow to scan mappers based on the same component-scanning path as Spring Boot itself.
(如果不存在mapper注册配置或mapper扫描配置,则此配置允许扫描mapper基于与Spring Boot本身相同的组件扫描路径。)
AutoConfiguredMapperScannerRegistrar
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
代码语言:javascript复制public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar {
private BeanFactory beanFactory;
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (!AutoConfigurationPackages.has(this.beanFactory)) {
logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.");
return;
}
logger.debug("Searching for mappers annotated with @Mapper");
List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
if (logger.isDebugEnabled()) {
packages.forEach(pkg -> logger.debug("Using auto-configuration base package '{}'", pkg));
}
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
builder.addPropertyValue("processPropertyPlaceHolders", true);
builder.addPropertyValue("annotationClass", Mapper.class); //指定扫描的注解
builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(packages)); //和springboot一致
BeanWrapper beanWrapper = new BeanWrapperImpl(MapperScannerConfigurer.class);
Stream.of(beanWrapper.getPropertyDescriptors())
// Need to mybatis-spring 2.0.2
.filter(x -> x.getName().equals("lazyInitialization")).findAny()
.ifPresent(x -> builder.addPropertyValue("lazyInitialization", "${mybatis.lazy-initialization:false}"));
registry.registerBeanDefinition(MapperScannerConfigurer.class.getName(), builder.getBeanDefinition());
}
}
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/137423.html原文链接:https://javaforall.cn