SpringBoot自动配置@EnableAutoConfiguration和@ImportAutoConfiguration的实现原理

@SpringBootApplication
class App {

}

// @SpringBootApplication
@SpringBootConfiguration
@EnableAutoConfiguration
@ImportAutoConfiguration
@ComponentScan(excludeFilters = {
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)})
@interface SpringBootApplication {

}

// 该注解就是一个普通的配置类标识
@Configuration
@interface SpringBootConfiguration {

}

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

}

// 该类和EnableAutoConfiguration效果差不多,ImportAutoConfigurationImportSelector也继承AutoConfigurationImportSelector
@Import(ImportAutoConfigurationImportSelector.class)
public @interface ImportAutoConfiguration {

}

/**
 * 导入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;
        }
    }

}

// 该类是一个延迟导入的类,通过@EnableAutoConfiguration注解导入的,该类会处理spring.factories中的配置类
class AutoConfigurationImportSelector implements DeferredImportSelector {
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        // 是否开启了自动导入功能,默认开启
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        // 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
        // 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
        // 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
        //      AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
        // 并将properties封装成PropertiesAutoConfigurationMetadata对象
        AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
        // 获取所有符合条件的需要自动导入的配置类,以及需要排除的配置类封装成自动导入条目对象返回
        AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
        // 返回所有符合条件的配置类
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }

    /**
     * 获取所有符合条件的需要自动导入的配置类,以及需要排除的配置类封装成自动导入条目对象返回
     * <pre>
     *     步骤:
     *          1. 检查自动导入功能是否开启,如果开启了接下一步(key: spring.boot.enableautoconfiguration)
     *          2. 从spring.factories中获取EnableAutoConfiguration的key对应所有类的名称
     * </pre>
     *
     * @param autoConfigurationMetadata // 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
     *                                  // 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
     *                                  // 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
     *                                  //      AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
     *                                  // 并将properties封装成PropertiesAutoConfigurationMetadata对象
     *                                  并将properties封装成PropertiesAutoConfigurationMetadata对象
     * @param annotationMetadata        标注@EnableAutoConfiguration注解所在的类的元数据
     * @return 所有自动导入的条目信息
     */
    protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
        // 是否开启了自动导入功能,默认开启
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        }
        // 获取@EnableAutoConfiguration的属性信息
        AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
        // 从spring.factories中获取EnableAutoConfiguration的key对应所有类的名称
        List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
        // 删除重复的配置,就是将List使用Set去重
        configurations = this.removeDuplicates(configurations);
        // 获取需要排除的类
        Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
        // 校验排除的类是否是一个正确的类,是在spring.factories中存在的类,如果不存在,抛出异常
        this.checkExcludedClasses(configurations, exclusions);
        // 从所有的配置类中删除要排除的类
        configurations.removeAll(exclusions);
        // 从spring.factories文件中加载AutoConfigurationImportFilter类型的实现类对自己装配的类进行过滤
        // 返回过滤后的配置类集合
        configurations = this.filter(configurations, autoConfigurationMetadata);
        // 从spring.factories文件中加载AutoConfigurationImportListener类型的实现类
        // 并触发这些监听器的onAutoConfigurationImportEvent方法
        this.fireAutoConfigurationImportEvents(configurations, exclusions);
        // 将所有需要导入的配置类以及需要排除的配置类封装成自动导入条目对象返回
        return new AutoConfigurationEntry(configurations, exclusions);
    }

    // 从spring.factories文件中加载AutoConfigurationImportListener类型的实现类
    // 并触发这些监听器的onAutoConfigurationImportEvent方法
    private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
        // 从spring.factories文件中加载AutoConfigurationImportListener类型的实现类
        List<AutoConfigurationImportListener> listeners = this.getAutoConfigurationImportListeners();
        // 如果存在监听器
        if (!listeners.isEmpty()) {
            // 发布一个自动导入配置的事件,将当前类,所有符合条件的配置类,以及需要排除的类封装
            AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
            // 遍历所有的监听器
            for (AutoConfigurationImportListener listener : listeners) {
                // 执行这些Aware回调方法
                this.invokeAwareMethods(listener);
                // 回调监听器的onAutoConfigurationImportEvent方法
                listener.onAutoConfigurationImportEvent(event);
            }
        }
    }

    // 执行对象的Aware接口方法
    private void invokeAwareMethods(Object instance) {
        if (instance instanceof Aware) {
            if (instance instanceof BeanClassLoaderAware) {
                ((BeanClassLoaderAware) instance).setBeanClassLoader(this.beanClassLoader);
            }
            if (instance instanceof BeanFactoryAware) {
                ((BeanFactoryAware) instance).setBeanFactory(this.beanFactory);
            }
            if (instance instanceof EnvironmentAware) {
                ((EnvironmentAware) instance).setEnvironment(this.environment);
            }
            if (instance instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) instance).setResourceLoader(this.resourceLoader);
            }
        }
    }

    // 从spring.factories文件中加载AutoConfigurationImportListener类型的实现类
    protected List<AutoConfigurationImportListener> getAutoConfigurationImportListeners() {
        return SpringFactoriesLoader.loadFactories(AutoConfigurationImportListener.class, this.beanClassLoader);
    }

    // 从spring.factories文件中加载AutoConfigurationImportFilter类型的实现类
    protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
        return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
    }

    // 从spring.factories文件中加载AutoConfigurationImportFilter类型的实现类对自己装配的类进行过滤
    // 返回过滤后的配置类集合
    private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) {
        long startTime = System.nanoTime();
        String[] candidates = StringUtils.toStringArray(configurations);
        boolean[] skip = new boolean[candidates.length];
        boolean skipped = false;
        // 从spring.factories文件中加载AutoConfigurationImportFilter类型的实现类
        List<AutoConfigurationImportFilter> filters = this.getAutoConfigurationImportFilters();
        // 遍历所有的过滤器
        for (AutoConfigurationImportFilter filter : filters) {
            // 执行filter的Aware方法
            // BeanClassLoaderAware,BeanFactoryAware,EnvironmentAware,ResourceLoaderAware
            this.invokeAwareMethods(filter);
            // 调用filter的过滤方法,返回一个对应这所有候选配置类数组是否被排除的数组,一一对应
            // 这里就是FilteringSpringBootCondition条件过滤器
            // 处理ConditionalOnBean,ConditionalOnSingleCandidate,ConditionalOnClass,ConditionalOnMissingClass,ConditionalOnWebApplication这些注解
            boolean[] match = filter.match(candidates, autoConfigurationMetadata);
            // 遍历这个对每一个类匹配的结果
            for (int i = 0; i < match.length; i++) {
                // 如果匹配失败
                if (!match[i]) {
                    // 标识当前配置类需要被跳过
                    skip[i] = true;
                    // 将候选的类置空,因为这是一个循环,还有多个AutoConfigurationImportFilter要进行处理
                    candidates[i] = null;
                    // 标识存在需要跳过的类
                    skipped = true;
                }
            }
        }
        // 如果不存在被跳过的类,那么直接返回传递过来的配置类
        if (!skipped) {
            return configurations;
        }
        // 有需要被跳过的类
        // 创建一个用于保存最终需要解析的配置类结果
        List<String> result = new ArrayList<>(candidates.length);
        // 遍历所有的配置类
        for (int i = 0; i < candidates.length; i++) {
            // 如果不需要被跳过
            if (!skip[i]) {
                // 保存配置
                result.add(candidates[i]);
            }
        }
        // 返回没有被跳过的类
        return new ArrayList<>(result);
    }

    // 校验排除的类是否是一个正确的类,是在spring.factories中存在的类,如果不存在,抛出异常
    private void checkExcludedClasses(List<String> configurations, Set<String> exclusions) {
        List<String> invalidExcludes = new ArrayList<>(exclusions.size());
        // 遍历已经要排除的类
        for (String exclusion : exclusions) {
            // 如果该类确实存在,并且在需要加载的所有配置类中不存在该排序的类
            if (ClassUtils.isPresent(exclusion, getClass().getClassLoader()) && !configurations.contains(exclusion)) {
                // 那么,该类表示无效的排除类
                invalidExcludes.add(exclusion);
            }
        }
        // 具有无效的排除类,抛出异常
        if (!invalidExcludes.isEmpty()) {
            this.handleInvalidExcludes(invalidExcludes);
        }
    }

    // 获取需要排除的类
    protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        Set<String> excluded = new LinkedHashSet<>();
        // 获取@EnableAutoConfiguration属性exclude的值
        excluded.addAll(asList(attributes, "exclude"));
        // 获取@EnableAutoConfiguration属性excludeName的值
        excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
        // 获取环境配置中的spring.autoconfigure.exclude的属性值这个配置的值表示忽略哪些文件
        excluded.addAll(this.getExcludeAutoConfigurationsProperty());
        return excluded;
    }

    // 获取环境配置中的spring.autoconfigure.exclude的属性值这个配置的值表示忽略哪些文件
    private List<String> getExcludeAutoConfigurationsProperty() {
        if (getEnvironment() instanceof ConfigurableEnvironment) {
            Binder binder = Binder.get(getEnvironment());
            // 获取环境对象中spring.autoconfigure.exclude的属性,并绑定到字符串数组中返回
            return binder.bind(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class).map(Arrays::asList).orElse(Collections.emptyList());
        }
        // 获取环境配置spring.autoconfigure.exclude的值
        String[] excludes = getEnvironment().getProperty(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class);
        return (excludes != null) ? Arrays.asList(excludes) : Collections.emptyList();
    }

    // 从spring.factories中获取EnableAutoConfiguration的key对应所有类的名称
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        // 从spring.factories中获取EnableAutoConfiguration的key对应所有类的名称
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, getBeanClassLoader());
        return configurations;
    }


    // 是否开启了自动导入功能
    protected boolean isEnabled(AnnotationMetadata metadata) {
        if (getClass() == AutoConfigurationImportSelector.class) {
            // 获取配置属性为"spring.boot.enableautoconfiguration"的值,默认为true
            return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);
        }
        return true;
    }

    // 自动配置的元数据加载器
    public class AutoConfigurationMetadataLoader {
        protected static final String PATH = "META-INF/spring-autoconfigure-metadata.properties";

        // 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
        // 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
        // 并将properties封装成PropertiesAutoConfigurationMetadata对象
        public static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
            return AutoConfigurationMetadataLoader.loadMetadata(classLoader, PATH);
        }


        // 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
        // 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
        // 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
        //      AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
        // 并将properties封装成PropertiesAutoConfigurationMetadata对象
        public static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {
            // 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件
            Enumeration<URL> urls = (classLoader != null) ? classLoader.getResources(path) : ClassLoader.getSystemResources(path);
            // 保存META-INF/spring-autoconfigure-metadata.properties中的所有配置
            Properties properties = new Properties();
            // 遍历所有的文件
            while (urls.hasMoreElements()) {
                // 将该配置类中所有的键值对保存到properties中
                properties.putAll(PropertiesLoaderUtils.loadProperties(new UrlResource(urls.nextElement())));
            }
            // 将所有属性配置封装为AutoConfigurationMetadata对象
            return AutoConfigurationMetadataLoader.loadMetadata(properties) {
                // 该对象就是从properties中获取对应的属性值
                return new PropertiesAutoConfigurationMetadata(properties);
            }
        }
    }

    // 延迟导入处理类的分组
    public static class AutoConfigurationGroup implements DeferredImportSelector.Group {
        // 所有需要导入的配置类=>导入的来源类的映射关系
        private final Map<String, AnnotationMetadata> entries = new LinkedHashMap<>();
        // 所有需要自动导入的配置类条目信息,每一个AutoConfigurationEntry对象包含了这个模块对应所有需要导入的类
        private final List<AutoConfigurationEntry> autoConfigurationEntries = new ArrayList<>();

        // 开始处理延迟导入的Bean操作
        public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
            // 将AutoConfigurationImportSelector类解析好的AutoConfigurationEntry获取出来
            AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector).getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
            // 保存到当前AutoConfigurationGroup类中
            this.autoConfigurationEntries.add(autoConfigurationEntry);
            // 遍历所有需要导入的配置类
            for (String importClassName : autoConfigurationEntry.getConfigurations()) {
                // 保存所有需要保存的配置类
                this.entries.putIfAbsent(importClassName, annotationMetadata);
            }
        }

        // 获取需要导入的所有类
        // 将配置类转换为Entry类型,key为: 导入该配置类的来源类 ,值为: 该配置类名称
        public Iterable<Entry> selectImports() {
            // 如果没有需要自动导入的条目
            if (this.autoConfigurationEntries.isEmpty()) {
                return Collections.emptyList();
            }
            // 过滤所有条目中需要排除的类
            Set<String> allExclusions = this.autoConfigurationEntries.stream().map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
            // 获取所有条目中需要导入的类
            Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
                    .map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
                    .collect(Collectors.toCollection(LinkedHashSet::new));
            // 将所有导入的类中删除需要排除的类
            processedConfigurations.removeAll(allExclusions);
            // 将所有配置类的优先级排序序之后
            return this.sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata())
                    .stream()
                    // 将配置类转换为Entry类型,key为: 导入该配置类的来源类 ,值为: 该配置类名称
                    .map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
                    .collect(Collectors.toList());
        }

        // 返回的是PropertiesAutoConfigurationMetadata
        // 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
        // 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
        // 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
        //      AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
        // 并将properties封装成PropertiesAutoConfigurationMetadata对象
        private AutoConfigurationMetadata getAutoConfigurationMetadata() {
            if (this.autoConfigurationMetadata == null) {
                // 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到autoConfigurationMetadata一个properties中
                this.autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
            }
            return this.autoConfigurationMetadata;
        }

        // 对说中配置类进行排序,最终得到所有配置类的加载顺序
        private List<String> sortAutoConfigurations(Set<String> classNames, AutoConfigurationMetadata autoConfigurationMetadata) {
            // 获取自动配置类的排序器
            AutoConfigurationSorter sorter = new AutoConfigurationSorter(getMetadataReaderFactory(), autoConfigurationMetadata);
            // 根据优先级排序,Order接口以及@AutoConfigureBefore @AutoConfigureAfter注解
            // 最终得到所有配置类的加载顺序
            List<String> result = sorter.getInPriorityOrder(classNames);
            return result;
        }

        // 获取"org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory"对应的元数据加载的工厂类的Bean
        private MetadataReaderFactory getMetadataReaderFactory() {
            // 获取"org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory"对应的元数据加载的工厂类的Bean
            return this.beanFactory.getBean(SharedMetadataReaderFactoryContextInitializer.BEAN_NAME, MetadataReaderFactory.class);
        }
    }

    // 自动配置类的排序器
    class AutoConfigurationSorter {
        // 类元数据的解析工厂
        private final MetadataReaderFactory metadataReaderFactory;
        // 自动配置类的属性配置元数据对象
        // 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
        // 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
        // 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
        //      AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
        // 并将properties封装成PropertiesAutoConfigurationMetadata对象
        private final AutoConfigurationMetadata autoConfigurationMetadata;

        // 根据优先级排序,Order接口以及@AutoConfigureBefore @AutoConfigureAfter注解
        // 最终得到所有配置类的加载顺序
        public List<String> getInPriorityOrder(Collection<String> classNames) {
            // 所有需要导入的类名,所有的META-INF/spring-autoconfigure-metadata.properties配置文件的数据对象包装成自动配置的类中AutoConfigurationClasses
            AutoConfigurationClasses classes = new AutoConfigurationClasses(this.metadataReaderFactory, this.autoConfigurationMetadata, classNames);
            List<String> orderedClassNames = new ArrayList<>(classNames);
            // 根据自然顺序进行排序
            Collections.sort(orderedClassNames);
            // 再根据Order接口进行排序
            orderedClassNames.sort((o1, o2) -> {
                int i1 = classes.get(o1).getOrder();
                int i2 = classes.get(o2).getOrder();
                return Integer.compare(i1, i2);
            });
            // 根据注解排序 @AutoConfigureBefore @AutoConfigureAfter
            orderedClassNames = this.sortByAnnotation(classes, orderedClassNames);
            return orderedClassNames;
        }

        // 根据注解排序 @AutoConfigureBefore @AutoConfigureAfter
        private List<String> sortByAnnotation(AutoConfigurationClasses classes, List<String> classNames) {
            // 所有需要排序的类
            List<String> toSort = new ArrayList<>(classNames);
            // 获取所有需要自动装配的配置类,包含了与给定的配置类存在加载关系的类
            toSort.addAll(classes.getAllNames());
            // 已经拍好序类
            Set<String> sorted = new LinkedHashSet<>();
            // 已经处理过的类
            Set<String> processing = new LinkedHashSet<>();
            // 如果有需要排序的类
            while (!toSort.isEmpty()) {
                // 使用@AfterAnnotation进行排序
                this.doSortByAfterAnnotation(classes, toSort, sorted, processing, null);
            }
            // 从已排好序的配置类中,删除在classNames中不存在的配置类
            // 因为我们只需要classNames中的元素
            sorted.retainAll(classNames);
            // 返回排好序的结果
            return new ArrayList<>(sorted);
        }

        //

        /**
         * 使用@AutoConfigureAfter注解进行排序,为什么没有按照@AutoConfigureBefore注解排序方法呢?
         * 因为{@link AutoConfigurationClasses#getClassesRequestedAfter(String)}中,统一时候后置进行排序
         * <pre>
         * 什么意思呢?
         *           如果我在你前面,那么,你就在我后面,因此,按照这种套路,就可以找到所有标记了我在他前面的类
         *           这样,就能拿到我后面的所有类,这样,从第一个类开始,就可以按照先后顺序排到最后一个
         * </pre>
         *
         * @param classes    需要排序的所有的类
         * @param toSort     需要排序的类
         * @param sorted     已经排好序的类
         * @param processing 正在进行排序的类
         * @param current    当前正在排序的类
         */
        private void doSortByAfterAnnotation(AutoConfigurationClasses classes, List<String> toSort, Set<String> sorted, Set<String> processing, String current) {
            // 如果当前排序的类为空,表示第一次使用这个类,取出第一个类开始排序
            // 如果不为空,表示是通过递归处理的
            if (current == null) {
                current = toSort.remove(0);
            }
            // 保存正在处理的类
            processing.add(current);
            // 获取需要在当前类之后加载的类
            Set<String> classesRequestedAfter = classes.getClassesRequestedAfter(current);
            for (String after : classesRequestedAfter) {
                // 如果未拍好序,并且该类需要排序
                if (!sorted.contains(after) && toSort.contains(after)) {
                    // 递归排序,因为要一层一层排
                    // 例如: a要在b后面,a还要在c后面,b又要在c后面,这种顺序逻辑关系
                    // 最终得到 a在b后面,a也在c后面
                    this.doSortByAfterAnnotation(classes, toSort, sorted, processing, after);
                }
            }
            // 该类存储完毕,移除该类
            processing.remove(current);
            // 表示该类已经排好序了
            sorted.add(current);
        }


        // 所有自动配置的类信息
        public static class AutoConfigurationClasses {
            // 保存所有需要自动装配的配置类,包含了与给定的配置类存在加载关系的类
            private final Map<String, AutoConfigurationClass> classes = new HashMap<>();

            /**
             * @param metadataReaderFactory     解析类元数据的工厂
             * @param autoConfigurationMetadata // 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
             *                                  // 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
             *                                  // 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
             *                                  //      AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
             *                                  // 并将properties封装成PropertiesAutoConfigurationMetadata对象
             * @param classNames                所有需要处理的配置类
             */
            public AutoConfigurationClasses(MetadataReaderFactory metadataReaderFactory, AutoConfigurationMetadata autoConfigurationMetadata, Collection<String> classNames) {
                // 将所有符合装配条件的配置类通过META-INF/spring-autoconfigure-metadata.properties或者@AutoConfigureOrder,@AutoConfigureAfter,@AutoConfigureBefore注解描述的关系
                // 将这些存在关系的类也进行保存,到时候也需要加载
                this.addToClasses(metadataReaderFactory, autoConfigurationMetadata, classNames, true);
            }

            /**
             * 将所有符合装配条件的配置类通过META-INF/spring-autoconfigure-metadata.properties或者@AutoConfigureOrder,@AutoConfigureAfter,@AutoConfigureBefore注解描述的关系
             * 将这些存在关系的类也进行保存,到时候也需要加载
             *
             * @param metadataReaderFactory     解析类元数据的工厂
             * @param autoConfigurationMetadata // 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
             *                                  // 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一
             *                                  // 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
             *                                  //      AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
             *                                  // 并将properties封装成PropertiesAutoConfigurationMetadata对象
             * @param classNames                所有需要处理的配置类
             * @param required                  是否必须加载
             */
            private void addToClasses(MetadataReaderFactory metadataReaderFactory, AutoConfigurationMetadata autoConfigurationMetadata, Collection<String> classNames, boolean required) {
                // 遍历所有的类名
                for (String className : classNames) {
                    // 如果该classes没有包含,表示没有处理过该类
                    if (!this.classes.containsKey(className)) {
                        // 创建单个自动配置类的信息,比如,要在那个类之后加载,之前加载等等
                        AutoConfigurationClass autoConfigurationClass = new AutoConfigurationClass(className, metadataReaderFactory, autoConfigurationMetadata);
                        // 该配置类是否可用
                        // 这个类在META-INF/spring-autoconfigure-metadata.properties中存在,或者可以成功加载这个类
                        boolean available = autoConfigurationClass.isAvailable();
                        // 如果必须,或者可用,required: 从构造方法调用的,为true,递归调用的为false
                        if (required || available) {
                            // 保存需要自动装配的配置类
                            this.classes.put(className, autoConfigurationClass);
                        }
                        // 配置类可用
                        if (available) {
                            // 不断递归添加要在该类之前加载的类
                            this.addToClasses(metadataReaderFactory, autoConfigurationMetadata, autoConfigurationClass.getBefore(), false);
                            // 不断递归添加要在该类后加载的类
                            this.addToClasses(metadataReaderFactory, autoConfigurationMetadata, autoConfigurationClass.getAfter(), false);
                        }
                    }
                }
            }

            // 获取所有需要自动装配的配置类,包含了与给定的配置类存在加载关系的类
            public Set<String> getAllNames() {
                return this.classes.keySet();
            }

            // 获取指定配置类的自动装配信息,比如,要在那个类之后加载,之前加载等等
            public AutoConfigurationClass get(String className) {
                return this.classes.get(className);
            }

            // 需要在该指定类之后加载的类
            public Set<String> getClassesRequestedAfter(String className) {
                // 获取需要在给定配置类之后加载的类名
                Set<String> after = this.get(className).getAfter();
                // 获取需要在该指定类之后加载的类
                Set<String> classesRequestedAfter = new LinkedHashSet<>(after);
                // 遍历所有需要加载的配置类信息
                this.classes.forEach((String name, AutoConfigurationClass autoConfigurationClass) -> {
                    // 获取需要在正在遍历的配置类之前加载的类,如果这些类中包含当前指定的类
                    // 那么表示指定的类就需要在正在遍历的类后面加载
                    if (autoConfigurationClass.getBefore().contains(className)) {
                        // 保存需要在当前指定的类后面加载的类
                        // 说白了就是className需要在正在遍历的类之前加载,反过来,正在遍历的类需要在指定的当前类之后加载
                        classesRequestedAfter.add(name);
                    }
                });
                // 需要在该指定类之后加载的类
                return classesRequestedAfter;
            }
        }

        // 单个自动配置类的信息,比如,要在那个类之后加载,之前加载等等
        public static class AutoConfigurationClass {
            // 配置类类名
            private final String className;
            // 解析类的元数据工厂
            private final MetadataReaderFactory metadataReaderFactory;
            // 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
            // 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
            // 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
            //      AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
            // 并将properties封装成PropertiesAutoConfigurationMetadata对象
            private final AutoConfigurationMetadata autoConfigurationMetadata;
            // 该配置类className对应的注解元信息
            private volatile AnnotationMetadata annotationMetadata;
            // 当前配置类在META-INF/spring-autoconfigure-metadata.properties配置的AutoConfigureBefore的类
            // 也就是需要在当前类之前进行配置的类
            private volatile Set<String> before;
            // 当前配置类在META-INF/spring-autoconfigure-metadata.properties配置的AutoConfigureAfter的类
            // 也就是需要在当前类之后进行配置的类
            private volatile Set<String> after;

            public AutoConfigurationClass(String className, MetadataReaderFactory metadataReaderFactory, AutoConfigurationMetadata autoConfigurationMetadata) {
                this.className = className;
                this.metadataReaderFactory = metadataReaderFactory;
                this.autoConfigurationMetadata = autoConfigurationMetadata;
            }

            // 该配置类是否可用
            // 这个类在META-INF/spring-autoconfigure-metadata.properties中存在,或者可以成功加载这个类
            public boolean isAvailable() {
                try {
                    // 该类在META-INF/spring-autoconfigure-metadata.properties是否存在配置信息
                    if (!this.wasProcessed()) {
                        // 获取该配置类对应的注解元信息,如果能获取到,表示该类存在,加载失败可能没引入这个类
                        this.getAnnotationMetadata();
                    }
                    // 这个类在META-INF/spring-autoconfigure-metadata.properties中存在,或者可以成功加载这个类
                    return true;
                } catch (Exception ex) {
                    // 该类不存在
                    return false;
                }
            }

            // 获取当前配置类在META-INF/spring-autoconfigure-metadata.properties配置文件中标识的AutoConfigureBefore对应的类
            public Set<String> getBefore() {
                if (this.before == null) {
                    // 所有的META-INF/spring-autoconfigure-metadata.properties配置文件的数据
                    this.before = (this.wasProcessed() ?
                            this.autoConfigurationMetadata.getSet(this.className, "AutoConfigureBefore", Collections.emptySet())
                            // 如果META-INF/spring-autoconfigure-metadata.properties配置文件中不存在,就只能加载类中的注解来获取
                            // 因为META-INF/spring-autoconfigure-metadata.properties中是对自动配置的优化,不用去解析类的元数据
                            : this.getAnnotationValue(AutoConfigureBefore.class));
                }
                return this.before;
            }

            // 获取当前配置类在META-INF/spring-autoconfigure-metadata.properties配置文件中标识的AutoConfigureAfter对应的类
            public Set<String> getAfter() {
                if (this.after == null) {
                    // 所有的META-INF/spring-autoconfigure-metadata.properties配置文件的数据
                    this.after = (this.wasProcessed() ? this.autoConfigurationMetadata.getSet(this.className, "AutoConfigureAfter", Collections.emptySet())
                            // 如果META-INF/spring-autoconfigure-metadata.properties配置文件中不存在,就只能加载类中的注解来获取
                            // 因为META-INF/spring-autoconfigure-metadata.properties中是对自动配置的优化,不用去解析类的元数据
                            : this.getAnnotationValue(AutoConfigureAfter.class));
                }
                return this.after;
            }

            // 获取当前配置类在META-INF/spring-autoconfigure-metadata.properties配置文件中标识的AutoConfigureOrder对应的类
            private int getOrder() {
                // 该类在META-INF/spring-autoconfigure-metadata.properties是否存在配置信息
                if (this.wasProcessed()) {
                    // 默认Order为0
                    return this.autoConfigurationMetadata.getInteger(this.className, "AutoConfigureOrder", AutoConfigureOrder.DEFAULT_ORDER);
                }
                // 该类在META-INF/spring-autoconfigure-metadata.properties不存在配置,就只能加载类中的注解来获取
                // 因为META-INF/spring-autoconfigure-metadata.properties中是对自动配置的优化,不用去解析类的元数据
                Map<String, Object> attributes = this.getAnnotationMetadata().getAnnotationAttributes(AutoConfigureOrder.class.getName());
                // 获取@AutoConfigureOrder注解对应的属性配置,默认值为:0
                return (attributes != null) ? (Integer) attributes.get("value") : AutoConfigureOrder.DEFAULT_ORDER;
            }

            // 该类在META-INF/spring-autoconfigure-metadata.properties是否存在配置信息
            private boolean wasProcessed() {
                // 该类在META-INF/spring-autoconfigure-metadata.properties中配置了,autoConfigurationMetadata中的properties中存在该类的Key,就表示需要被加载
                return (this.autoConfigurationMetadata != null && this.autoConfigurationMetadata.wasProcessed(this.className));
            }

            /**
             * 获取指定注解的属性,包含@AutoConfigureAfter,@AutoConfigureBefore
             *
             * @param annotation 注解信息,@AutoConfigureAfter,@AutoConfigureBefore
             * @return 该注解配置的value和name值
             */
            private Set<String> getAnnotationValue(Class<?> annotation) {
                // 获取该类的元数据中的指定注解信息
                Map<String, Object> attributes = this.getAnnotationMetadata().getAnnotationAttributes(annotation.getName(), true);
                // 如果不存在指定注解
                if (attributes == null) {
                    return Collections.emptySet();
                }
                // 存在指定注解
                Set<String> value = new LinkedHashSet<>();
                // 保存该注解的value和name值
                Collections.addAll(value, (String[]) attributes.get("value"));
                Collections.addAll(value, (String[]) attributes.get("name"));
                return value;
            }

            // 获取该配置类对应的注解元信息
            private AnnotationMetadata getAnnotationMetadata() {
                if (this.annotationMetadata == null) {
                    // 加载该配置类的元信息
                    MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(this.className);
                    // 获取该配置类对应的注解元信息
                    this.annotationMetadata = metadataReader.getAnnotationMetadata();
                }
                return this.annotationMetadata;
            }

        }

        // 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
        // 该配置文件存储着自动配置类的装配条件,这些与在类中配置的注解效果是一样的
        // 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
        //      AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
        // 并将properties封装成PropertiesAutoConfigurationMetadata对象
        public static class PropertiesAutoConfigurationMetadata implements AutoConfigurationMetadata {
            // 保存这所有META-INF/spring-autoconfigure-metadata.properties的配置信息
            private final Properties properties;

            public PropertiesAutoConfigurationMetadata(Properties properties) {
                this.properties = properties;
            }

            // 该类在META-INF/spring-autoconfigure-metadata.properties配置文件是否存在
            public boolean wasProcessed(String className) {
                return this.properties.containsKey(className);
            }

            // 获取int类型的值
            public Integer getInteger(String className, String key) {
                return getInteger(className, key, null);
            }

            public Integer getInteger(String className, String key, Integer defaultValue) {
                String value = get(className, key);
                return (value != null) ? Integer.valueOf(value) : defaultValue;
            }

            // 获取set类型的值
            public Set<String> getSet(String className, String key) {
                return getSet(className, key, null);
            }

            public Set<String> getSet(String className, String key, Set<String> defaultValue) {
                String value = get(className, key);
                return (value != null) ? StringUtils.commaDelimitedListToSet(value) : defaultValue;
            }

            // 获取String类型的值
            public String get(String className, String key) {
                return get(className, key, null);
            }

            public String get(String className, String key, String defaultValue) {
                String value = this.properties.getProperty(className + "." + key);
                return (value != null) ? value : defaultValue;
            }

        }

    }

}

/**
 * 处理@ImportAutoConfiguration注解的类
 *
 * @see {@link AutoConfigurationImportSelector}
 */
class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelector {
    // 可以解析的注解名
    private static final Set<String> ANNOTATION_NAMES;

    // 该类会处理@ImportAutoConfiguration和测试包的test.ImportAutoConfiguration注解
    static {
        Set<String> names = new LinkedHashSet<>();
        // @ImportAutoConfiguration
        names.add(ImportAutoConfiguration.class.getName());
        // 测试包的@ImportAutoConfiguration注解
        names.add("org.springframework.boot.autoconfigure.test.ImportAutoConfiguration");
        ANNOTATION_NAMES = Collections.unmodifiableSet(names);
    }

    /**
     * 确定需要导入的类
     *
     * @param metadata 标注@ImportAutoConfiguration类的元信息
     */
    public Set<Object> determineImports(AnnotationMetadata metadata) {
        // 获取候选的配置类,该类重写了默认的从spring.factories获取配置,而是从@ImportAutoConfiguration注解中获取需要导入的类
        List<String> candidateConfigurations = this.getCandidateConfigurations(metadata, null);
        Set<String> result = new LinkedHashSet<>(candidateConfigurations);
        // 获取需要排除的类
        Set<String> exclusions = this.getExclusions(metadata, null);
        // 在获取的所有候选配置类中,删除要排除的类
        result.removeAll(exclusions);
        // 返回所有符合条件的配置类
        return Collections.unmodifiableSet(result);
    }

    // 该类不处理
    @Override
    protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
        return null;
    }

    /**
     * 获取候选的配置类,该类重写了默认的从spring.factories获取配置
     *
     * @param metadata   标注@ImportAutoConfiguration类的元信息
     * @param attributes 注解属性信息,这个为空,因为当前类覆盖了父类的{@link ImportAutoConfigurationImportSelector#getAttributes}方法
     * @return 所有符合条件的配置类
     */
    @Override
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> candidates = new ArrayList<>();
        // 收集入口配置类中所有的@ImportAutoConfiguration注解信息,包括注解中的,父类的
        // Key为出现@ImportAutoConfiguration的类的Class,Value为@ImportAutoConfiguration注解信息
        // 用List作为Value是同时为了处理org.springframework.boot.autoconfigure.test.ImportAutoConfiguration注解
        Map<Class<?>, List<Annotation>> annotations = this.getAnnotations(metadata);
        // 遍历所有收集到了@ImportAutoConfiguration注解信息
        annotations.forEach((source, sourceAnnotations) -> this.collectCandidateConfigurations(source, sourceAnnotations, candidates));
        // 返回所有需要加载的配置类
        return candidates;
    }

    /**
     * 收集@ImportAutoConfiguration注解中需要导入的配置类信息
     *
     * @see {@link ImportAutoConfigurationImportSelector#getConfigurationsForAnnotation}
     */
    private void collectCandidateConfigurations(Class<?> source, List<Annotation> annotations, List<String> candidates) {
        // 遍历该配置类中存在的所有@ImportAutoConfiguration注解
        // 用List作为Value是同时为了处理org.springframework.boot.autoconfigure.test.@ImportAutoConfiguration注解
        // 因为这个配置类可以同时配置这两个注解
        for (Annotation annotation : annotations) {
            // 从@ImportAutoConfiguration注解信息中,获取需要导入的配置类
            Collection<String> forAnnotation = this.getConfigurationsForAnnotation(source, annotation);
            // 保存所有注解中导入的所有类的信息
            candidates.addAll(forAnnotation);
        }
    }

    /**
     * 从@ImportAutoConfiguration注解信息中,获取需要导入的配置类
     * <pre>
     *      1. 如果@ImportAutoConfiguration标注了需要导入的类,那么导入的那个类才是配置类
     *      2. 如果@ImportAutoConfiguration没有标注需要导入的类,只有一个注解
     *           那么会加载标注该注解的类作为Key,从spring.factories获取对应的配置信息
     *           例如:
     *              @ImportAutoConfiguration
     *              class A{}
     *              那么,会自动从spring.factories中找a的全类名对应的配置类信息
     *     2.1 再举个例子: 在自己项目中,创建一个org.springframework.boot.autoconfigure.EnableAutoConfiguration类
     *                   在类中标注@ImportAutoConfiguration注解,并将EnableAutoConfiguration类设置为SpringApplication的配置类
     *                   那么,与@EnableAutoConfiguration的作用几乎一样,但是一般不会这么做
     *  </pre>
     *
     * @param source     标注@ImportAutoConfiguration注解的为了或者注解
     * @param annotation @ImportAutoConfiguration注解信息
     * @return 所有配置类信息
     */
    private Collection<String> getConfigurationsForAnnotation(Class<?> source, Annotation annotation) {
        // 获取@ImportAutoConfiguration注解的信息
        String[] classes = (String[]) AnnotationUtils.getAnnotationAttributes(annotation, true).get("classes");
        // 如果配置了导入的配置类,那么直接返回这个配置类
        if (classes.length > 0) {
            return Arrays.asList(classes);
        }
        // 如果没有配置,那么会加载标注该注解的类作为Key,从spring.factories获取对应的配置信息
        return loadFactoryNames(source);
    }

    // 根据指定类型名从spring.factories中获取该key对应的配置类信息
    protected Collection<String> loadFactoryNames(Class<?> source) {
        return SpringFactoriesLoader.loadFactoryNames(source, getClass().getClassLoader());
    }

    // 获取需要排除的类
    @Override
    protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        // 所有需要的排除的类
        Set<String> exclusions = new LinkedHashSet<>();
        // 解析标注了@ImportAutoConfiguration注解的类(入口配置类)
        Class<?> source = ClassUtils.resolveClassName(metadata.getClassName(), null);
        // 遍历当前类所有的支持处理的注解
        for (String annotationName : ANNOTATION_NAMES) {
            // 获取到注解的属性信息
            AnnotationAttributes merged = AnnotatedElementUtils.getMergedAnnotationAttributes(source, annotationName);
            // 获取注解中需要排除的类
            Class<?>[] exclude = (merged != null) ? merged.getClassArray("exclude") : null;
            // 如果配置了
            if (exclude != null) {
                // 保存需要排除的类名
                for (Class<?> excludeClass : exclude) {
                    exclusions.add(excludeClass.getName());
                }
            }
        }
        // 再解析入口配置类中所有的@ImportAutoConfiguration注解信息,包括注解中的,父类的
        // 获取收集到的所有@ImportAutoConfiguration信息
        List<Annotation>[] values = this.getAnnotations(metadata).values();
        for (List<Annotation> annotations : values) {
            // 遍历所有的@ImportAutoConfiguration注解
            for (Annotation annotation : annotations) {
                // 获取该注解的排除类属性
                String[] exclude = (String[]) AnnotationUtils.getAnnotationAttributes(annotation, true).get("exclude");
                // 如果不为空
                if (!ObjectUtils.isEmpty(exclude)) {
                    // 保存需要排除的类
                    exclusions.addAll(Arrays.asList(exclude));
                }
            }
        }
        return exclusions;
    }

    // 收集入口配置类中所有的@ImportAutoConfiguration注解信息,包括注解中的,父类的
    protected final Map<Class<?>, List<Annotation>> getAnnotations(AnnotationMetadata metadata) {
        MultiValueMap<Class<?>, Annotation> annotations = new LinkedMultiValueMap<>();
        // 解析标注了@ImportAutoConfiguration类的类名
        Class<?> source = ClassUtils.resolveClassName(metadata.getClassName(), null);
        // 收集入口配置类中所有的@ImportAutoConfiguration注解信息,包括注解中的,父类的
        this.collectAnnotations(source, annotations, new HashSet<>());
        return Collections.unmodifiableMap(annotations);
    }

    /**
     * 收集入口配置类中所有的@ImportAutoConfiguration注解信息,包括注解中的,父类的
     *
     * @param source      需要收集@ImportAutoConfiguration注解的类的信息
     * @param annotations 需要保存该source中的所有@ImportAutoConfiguration注解的类
     * @param seen        已经处理过的类
     */
    private void collectAnnotations(Class<?> source, MultiValueMap<Class<?>, Annotation> annotations, HashSet<Class<?>> seen) {
        // 如果需要收集注解的类不为空,并且没有处理过
        if (source != null && seen.add(source)) {
            // 获取类中所有的注解
            for (Annotation annotation : source.getDeclaredAnnotations()) {
                // 如果不是java.lang.annotation包中的注解
                if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation)) {
                    // 如果存在@ImportAutoConfiguration注解
                    if (ANNOTATION_NAMES.contains(annotation.annotationType().getName())) {
                        // 保存该类与该@ImportAutoConfiguration注解的映射关系
                        annotations.add(source, annotation);
                    }
                    // 再根据当前注解类型再去找注解中的@ImportAutoConfiguration注解信息
                    this.collectAnnotations(annotation.annotationType(), annotations, seen);
                }
            }
            // 找完了当前类,继续收集父类的@ImportAutoConfiguration注解信息
            this.collectAnnotations(source.getSuperclass(), annotations, seen);
        }
    }

    // 在AutoConfigurationImportSelector之前执行
    @Override
    public int getOrder() {
        return super.getOrder() - 1;
    }

    // 处理用户排除的无效的类
    @Override
    protected void handleInvalidExcludes(List<String> invalidExcludes) {
    }
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值