@MapperScan 掃描包流程分析
以下文章來(lái)源于武培軒,回復(fù)資源獲取資料
前言
其實(shí)一般不寫(xiě)這樣的分析的,但是這次呢一是為了記錄下來(lái)分析過(guò)程,二是給大家分享一下@MapperScan注解掃描包的流程吧。
提出問(wèn)題
@MapperScan("com.fast")掃描的是com.fast這個(gè)包下面的bean是毋庸置疑的,但是包括子包下面的bean嗎?
疑問(wèn)案例
比如com.fast.master.dao,還有com.fast.second.dao這些包下面的bean是否會(huì)一起被掃描到?
分析
查看MapperScan注解,掃描包主要是這個(gè) @Import({MapperScannerRegistrar.class})
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({MapperScannerRegistrar.class})
@Repeatable(MapperScans.class)
public @interface MapperScan {
String[] value() default {};
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
Class<? extends Annotation> annotationClass() default Annotation.class;
Class<?> markerInterface() default Class.class;
String sqlSessionTemplateRef() default "";
String sqlSessionFactoryRef() default "";
Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class;
}
找到MapperScannerRegistrar.class看實(shí)現(xiàn)過(guò)程,就不全貼了,主要是這個(gè)注解這一塊
void registerBeanDefinitions(AnnotationAttributes annoAttrs, BeanDefinitionRegistry registry) {
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
Optional var10000 = Optional.ofNullable(this.resourceLoader);
Objects.requireNonNull(scanner);
var10000.ifPresent(scanner::setResourceLoader);
Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
if (!Annotation.class.equals(annotationClass)) {
scanner.setAnnotationClass(annotationClass);
}
Class<?> markerInterface = annoAttrs.getClass("markerInterface");
if (!Class.class.equals(markerInterface)) {
scanner.setMarkerInterface(markerInterface);
}
Class<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator");
if (!BeanNameGenerator.class.equals(generatorClass)) {
scanner.setBeanNameGenerator((BeanNameGenerator)BeanUtils.instantiateClass(generatorClass));
}
Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
scanner.setMapperFactoryBeanClass(mapperFactoryBeanClass);
}
scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));
List<String> basePackages = new ArrayList();
basePackages.addAll((Collection)Arrays.stream(annoAttrs.getStringArray("value")).filter(StringUtils::hasText).collect(Collectors.toList()));
basePackages.addAll((Collection)Arrays.stream(annoAttrs.getStringArray("basePackages")).filter(StringUtils::hasText).collect(Collectors.toList()));
basePackages.addAll((Collection)Arrays.stream(annoAttrs.getClassArray("basePackageClasses")).map(ClassUtils::getPackageName).collect(Collectors.toList()));
scanner.registerFilters();
scanner.doScan(StringUtils.toStringArray(basePackages));
}
這句周?chē)氖遣皇呛苁煜ぃ褪荕apperScan實(shí)現(xiàn)的注解,value,basePackages,basePackageClasses這幾個(gè)
basePackages.addAll((Collection)Arrays.stream(annoAttrs.getStringArray("value")).filter(StringUtils::hasText).collect(Collectors.toList()));
basePackages.addAll((Collection)Arrays.stream(annoAttrs.getStringArray("basePackages")).filter(StringUtils::hasText).collect(Collectors.toList()));
basePackages.addAll((Collection)Arrays.stream(annoAttrs.getClassArray("basePackageClasses")).map(ClassUtils::getPackageName).collect(Collectors.toList()));
scanner.registerFilters();
scanner.doScan(StringUtils.toStringArray(basePackages));
從scanner.doScan這句進(jìn)去,這里是開(kāi)始掃描包的地方
打開(kāi)調(diào)用的方法
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
Iterator var3 = beanDefinitions.iterator();
while(var3.hasNext()) {
BeanDefinitionHolder holder = (BeanDefinitionHolder)var3.next();
GenericBeanDefinition definition = (GenericBeanDefinition)holder.getBeanDefinition();
String beanClassName = definition.getBeanClassName();
LOGGER.debug(() -> {
return "Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + beanClassName + "' mapperInterface";
});
definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);
definition.setBeanClass(this.mapperFactoryBeanClass);
definition.getPropertyValues().add("addToConfig", this.addToConfig);
boolean explicitFactoryUsed = false;
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;
}
if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
if (explicitFactoryUsed) {
LOGGER.warn(() -> {
return "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.";
});
}
definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
explicitFactoryUsed = true;
} else if (this.sqlSessionTemplate != null) {
if (explicitFactoryUsed) {
LOGGER.warn(() -> {
return "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.";
});
}
definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
explicitFactoryUsed = true;
}
if (!explicitFactoryUsed) {
LOGGER.debug(() -> {
return "Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.";
});
definition.setAutowireMode(2);
}
}
}
從這個(gè)方法第一行開(kāi)始debug,這里我使用@MapperScan("com.fast.framework.dao") 是掃描的com.fast.framework.dao包

這個(gè)是掃描到的包,說(shuō)明會(huì)掃描到子包,perfect,解決了開(kāi)始提出的問(wèn)題。

總結(jié)
其實(shí)這里的分析過(guò)程不是特別詳細(xì),因?yàn)榈竭@里是證明掃描出來(lái)的包,從而間接證明掃描到的包都會(huì)被使用。剩下的:上一步怎么掃描的全部包,還有掃描到包怎么初始化的都沒(méi)有詳細(xì)分析。所以也是小水一篇吧,主要是要明白@MapperScan注解會(huì)掃描包的子包和學(xué)會(huì)這種分析思路。
來(lái)源:blog.csdn.net/Mint6/article/details/92441513
覺(jué)得不錯(cuò),請(qǐng)點(diǎn)個(gè)在看呀
評(píng)論
圖片
表情
