作用
误区:
springBoot默认扫描bean的配置是启动类的上一级目录,也是通过@AutoConfigurationPackage产生的
(因为此注解翻译过来的意思就是自动注入包配置,容易理解偏差)
说明:
而 AutoConfigurationPackage 更多的是提供了一个工具或接口,我们可以通过它获取自动配置的package列表。也就是说 ComponentScan 更多的是spring自用,AutoConfigurationPackage 是它用。
扩展:
Spring 依据 ComponentScan 指定的 package 进行组件扫描;而@ComponentScan注解默认没有配置package,会从启动类的路径中选它的当前目录作为bean扫描的路径。具体分析可见我的这篇文章:ComponentScan为什么默认扫描的也是启动类下面的目录呢
使用场景
mybatis @Mapper 源码分析
AutoConfigurationPackage 分析
public static void register(BeanDefinitionRegistry registry, String... packageNames) {
if (registry.containsBeanDefinition(BEAN)) {
BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues();
constructorArguments.addIndexedArgumentValue(0, addBasePackages(constructorArguments, packageNames));
}
else {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(BasePackages.class);
// 通过有参构造赋值第一个属性
beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(BEAN, beanDefinition);
}
}
static final class BasePackages {
private final List<String> packages;
private boolean loggedBasePackageInfo;
BasePackages(String... names) {
List<String> packages = new ArrayList<>();
for (String name : names) {
if (StringUtils.hasText(name)) {
packages.add(name);
}
}
this.packages = packages;
}
}