SpringBoot中,@EnableAutoConfiguration包含的@AutoConfigurationPackage有什么用,具体做了什么

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
@interface EnableAutoConfiguration {

}

/**
 * 导入Registrar类,该类主要是导入BasePackages类,保存了需要扫描的包的信息
 *
 * @see {@link AutoConfigurationPackages.BasePackages}
 * @see {@link AutoConfigurationPackages.Registrar#registerBeanDefinitions}
 * 该类的作用就是将标@AutoConfigurationPackage注解的类的包名封装成BasePackages对象,然后注册为Bean
 * <p/>
 * 对于其他外部,如果需要获取到SpringBoot需要自动扫描的包,则可以获取BasePackages这个Bean
 * @see {@link AutoConfigurationPackages#get}
 * BeanName固定为AutoConfigurationPackages.class.getName
 */
@Import(AutoConfigurationPackages.Registrar.class)
@interface AutoConfigurationPackage {

}

// 自动配置标注了@AutoConfigurationPackage类作为需要扫描的包名
class AutoConfigurationPackages {
    private static final String BEAN = AutoConfigurationPackages.class.getName();

    static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
        @Override
        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
            // 注册BasePackages的Bean对象,保存了标注@AutoConfigurationPackage注解的类对应的包名
            AutoConfigurationPackages.register(registry, new PackageImport(metadata).getPackageName());
        }

        // 确定导入包的信息
        @Override
        public Set<Object> determineImports(AnnotationMetadata metadata) {
            return Collections.singleton(new PackageImport(metadata));
        }
    }

    // 是否存在BasePackages的Bean对象
    public static boolean has(BeanFactory beanFactory) {
        return beanFactory.containsBean(BEAN) && !AutoConfigurationPackages.get(beanFactory).isEmpty();
    }

    // 获取需要扫描的包对应的Bean对象
    public static List<String> get(BeanFactory beanFactory) {
        try {
            return beanFactory.getBean(BEAN, BasePackages.class).get();
        } catch (NoSuchBeanDefinitionException ex) {
            throw new IllegalStateException("Unable to retrieve @EnableAutoConfiguration base packages");
        }
    }

    // 注册BasePackages的Bean对象,保存了标注@AutoConfigurationPackage注解的类对应的包名
    public static void register(BeanDefinitionRegistry registry, String... packageNames) {
        // 如果容器中包含"AutoConfigurationPackages" => BasePackages这个Bean
        if (registry.containsBeanDefinition(BEAN)) {
            // 获取该Bean的BeanDefinition
            BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
            // 添加构造参数
            ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues();
            // 将构造函数参数中的需要扫描的包名与给定的包名进行合并
            String[] packages = AutoConfigurationPackages.addBasePackages(constructorArguments, packageNames);
            // 重新添加进去
            constructorArguments.addIndexedArgumentValue(0, packages);
            return;
        }
        // 如果不存在BasePackagesBean,创建一个BasePackages的Bean对象
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(BasePackages.class);
        // 添加构造参数
        beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);
        beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        // 注册Bean
        registry.registerBeanDefinition(BEAN, beanDefinition);
    }

    // 将构造函数参数中的需要扫描的包名与给定的包名进行合并
    private static String[] addBasePackages(ConstructorArgumentValues constructorArguments, String[] packageNames) {
        String[] existing = (String[]) constructorArguments.getIndexedArgumentValue(0, String[].class).getValue();
        Set<String> merged = new LinkedHashSet<>();
        merged.addAll(Arrays.asList(existing));
        merged.addAll(Arrays.asList(packageNames));
        return StringUtils.toStringArray(merged);
    }


    // 保存标注了@AutoConfigurationPackage类的包名
    public static final class PackageImport {

        // 保存标注了@AutoConfigurationPackage类的包名
        private final String packageName;

        // 注解的元信息
        public PackageImport(AnnotationMetadata metadata) {
            // 获取到标注注解的类对应的类名
            this.packageName = ClassUtils.getPackageName(metadata.getClassName());
        }

        public String getPackageName() {
            return this.packageName;
        }
    }

    // 保存所有需要扫描的包名
    // 该对象会作为Spring中的Bean对象
    public static final class BasePackages {
        // 需要扫描的包名,该字段是通过beanDefinition.getConstructorArgumentValues()通过构造参数传递的
        private final List<String> packages;

        public BasePackages(String... names) {
            List<String> packages = new ArrayList<>();
            // 遍历所有的包名
            for (String name : names) {
                // 保存这些需要扫描的包名
                packages.add(name);
            }
            this.packages = packages;
        }

        List<String> get() {
            return this.packages;
        }
    }

}

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值