springBoot自动配置原理源码剖析

​ SpringBoot 知识点汇总

  1. SpringBoot 自动配置的原理?

​ 首先自动配置是配置spring-boot-autoconfigure-2.0.4.RELEASE.jar包下MATA-INF下的spring.properties 文件中org.springframework.boot.autoconfigure.EnableAutoConfiguration所对应自动配置类。

其次springBoot启动类中的@springBootApplication隐含的引入了EnableAutoConfigurationImportSelector;

// 注解链
@SpringBootApplication
    => @EnableAutoConfiguration
        => @Import(EnableAutoConfigurationImportSelector.class)

在SpringApplication的run方法中,会调context = createApplicationContext();在实例化这个ConfigurableApplicationContext时,不管是AnnotationConfigEmbeddedWebApplicationContextAnnotationConfigApplicationContext时(这两个类是专门处理Spring注解方式配置的容器,直接依赖于注解作为容器配置信息来源的IoC容器。 AnnotationConfigWebApplicationContextAnnotationConfigApplicationContext的web版本,两者的用法以及对注解的处理方式几乎没有什么差别),都会实例化一个AnnotatedBeanDefinitionReader。例如AnnotationConfigEmbeddedWebApplicationContext实例化代码:

 public AnnotationConfigEmbeddedWebApplicationContext() {
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }
​

​ 这里将构造AnnotatedBeanDefinitionReader,在AnnotatedBeanDefinitionReader实例化过程中,会向beanFactory注册CommonAnnotationBeanPostProcessorAutowiredAnnotationBeanPostProcessorConfigurationClassPostProcessor等:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, Object source) {
​
        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
        if (beanFactory != null) {
            if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
            }
            if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
            }
        }
​
        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
​
        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
​
        if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
​
        if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
​
        // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
        if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
​
        // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
        if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition();
            try {
                def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                        AnnotationConfigUtils.class.getClassLoader()));
            }
            catch (ClassNotFoundException ex) {
                throw new IllegalStateException(
                        "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
            }
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
​
        if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
        }
        if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
        }
​
        return beanDefs;
    }

也就是说createApplicationContext()完后,beanFactory的beanDefinitionMap会有6个值。

SpringApplication的run方法中,在调用createApplicationContext();后会调用prepareContext(context, environment, listeners, applicationArguments,printedBanner)

 private void prepareContext(ConfigurableApplicationContext context,
            ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
            ApplicationArguments applicationArguments, Banner printedBanner) {
        // ….
        // Load the sources
        Set<Object> sources = getSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        load(context, sources.toArray(new Object[sources.size()]));
        listeners.contextLoaded(context);
    }

getSources()返回的就是new SpringApplication(Application.class)传入的参数,即我们的主类,然后调用了load()方法,在load()中会生成BeanDefinitionLoader实例,并把主类注册到IOC容器中。

  OK,到这里即在调用我们熟悉的AbstractApplicationContext#refresh()前,beanFactory有7个定义好的beanDefinition。

public void refresh() throws BeansException, IllegalStateException {
    Object var1 = this.startupShutdownMonitor;
    synchronized(this.startupShutdownMonitor) {
        this.prepareRefresh();
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
        this.prepareBeanFactory(beanFactory);
​
        try {
            this.postProcessBeanFactory(beanFactory);
            this.invokeBeanFactoryPostProcessors(beanFactory);
            this.registerBeanPostProcessors(beanFactory);
            this.initMessageSource();
            this.initApplicationEventMulticaster();
            this.onRefresh();
            this.registerListeners();
            this.finishBeanFactoryInitialization(beanFactory);
            this.finishRefresh();
        } catch (BeansException var9) {
            if (this.logger.isWarnEnabled()) {
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
            }
​
            this.destroyBeans();
            this.cancelRefresh(var9);
            throw var9;
        } finally {
            this.resetCommonCaches();
        }
​
    }
}

ConfigurationClassPostProcessorBeanFactoryPostProcessor的子类,会在Spring容器refresh时,invokeBeanFactoryPostProcessors(beanFactory)方法中调用到。ConfigurationClassPostProcessor会解析到我们的主类,把@Import中的类拿出来,调用它的selectImports()方法。

ConfigurationClassPostProcessor 中ConfigurationClassParser分析配置类时,如果发现注@Import(ImportSelector)的情况,就会创建一个相应的ImportSelector对象, 并调用其方法 public String[] selectImports(AnnotationMetadata annotationMetadata), 这里 EnableAutoConfigurationImportSelector的导入@Import(EnableAutoConfigurationImportSelector.class) 就属于这种情况,所以ConfigurationClassParser会实例化一个 EnableAutoConfigurationImportSelector 并调用它的 selectImports() 方法。

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    int registryId = System.identityHashCode(registry);
    if (this.registriesPostProcessed.contains(registryId)) {
        throw new IllegalStateException("postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
    } else if (this.factoriesPostProcessed.contains(registryId)) {
        throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + registry);
    } else {
        this.registriesPostProcessed.add(registryId);
        this.processConfigBeanDefinitions(registry);
    }
} //BeanFactoryPostProcessor接口唯一的方法,被ConfigurationClassPostProcessor实现了;
​
//该方法中对配置类中的@import中的类进行解析
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    List<BeanDefinitionHolder> configCandidates = new ArrayList();
    String[] candidateNames = registry.getBeanDefinitionNames();
    String[] var4 = candidateNames;
    int var5 = candidateNames.length;
​
    for(int var6 = 0; var6 < var5; ++var6) {
        String beanName = var4[var6];
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        if (!ConfigurationClassUtils.isFullConfigurationClass(beanDef) && !ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
            if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        } else if (this.logger.isDebugEnabled()) {
            this.logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
        }
    }
​
    if (!configCandidates.isEmpty()) {
        configCandidates.sort((bd1, bd2) -> {
            int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
            int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
            return Integer.compare(i1, i2);
        });
        SingletonBeanRegistry sbr = null;
        if (registry instanceof SingletonBeanRegistry) {
            sbr = (SingletonBeanRegistry)registry;
            if (!this.localBeanNameGeneratorSet) {
                BeanNameGenerator generator = (BeanNameGenerator)sbr.getSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator");
                if (generator != null) {
                    this.componentScanBeanNameGenerator = generator;
                    this.importBeanNameGenerator = generator;
                }
            }
        }
​
        if (this.environment == null) {
            this.environment = new StandardEnvironment();
        }
​
        ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
        Set<BeanDefinitionHolder> candidates = new LinkedHashSet(configCandidates);
        HashSet alreadyParsed = new HashSet(configCandidates.size());
​
        do {
            parser.parse(candidates);
            parser.validate();
            Set<ConfigurationClass> configClasses = new LinkedHashSet(parser.getConfigurationClasses());
            configClasses.removeAll(alreadyParsed);
            if (this.reader == null) {
                this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry());
            }
​
            this.reader.loadBeanDefinitions(configClasses);
            alreadyParsed.addAll(configClasses);
            candidates.clear();
            if (registry.getBeanDefinitionCount() > candidateNames.length) {
                String[] newCandidateNames = registry.getBeanDefinitionNames();
                Set<String> oldCandidateNames = new HashSet(Arrays.asList(candidateNames));
                Set<String> alreadyParsedClasses = new HashSet();
                Iterator var12 = alreadyParsed.iterator();
​
                while(var12.hasNext()) {
                    ConfigurationClass configurationClass = (ConfigurationClass)var12.next();
                    alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
                }
​
                String[] var23 = newCandidateNames;
                int var24 = newCandidateNames.length;
​
                for(int var14 = 0; var14 < var24; ++var14) {
                    String candidateName = var23[var14];
                    if (!oldCandidateNames.contains(candidateName)) {
                        BeanDefinition bd = registry.getBeanDefinition(candidateName);
                        if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                            candidates.add(new BeanDefinitionHolder(bd, candidateName));
                        }
                    }
                }
​
                candidateNames = newCandidateNames;
            }
        } while(!candidates.isEmpty());
​
        if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
            sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
        }
​
        if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
            ((CachingMetadataReaderFactory)this.metadataReaderFactory).clearCache();
        }
​
    }
}
public void parse(Set<BeanDefinitionHolder> configCandidates) {
    this.deferredImportSelectors = new LinkedList();
    Iterator var2 = configCandidates.iterator();
​
    while(var2.hasNext()) {
        BeanDefinitionHolder holder = (BeanDefinitionHolder)var2.next();
        BeanDefinition bd = holder.getBeanDefinition();
​
        try {
            if (bd instanceof AnnotatedBeanDefinition) {
                this.parse(((AnnotatedBeanDefinition)bd).getMetadata(), holder.getBeanName());
            } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) {
                this.parse(((AbstractBeanDefinition)bd).getBeanClass(), holder.getBeanName());
            } else {
                this.parse(bd.getBeanClassName(), holder.getBeanName());
            }
        } catch (BeanDefinitionStoreException var6) {
            throw var6;
        } catch (Throwable var7) {
            throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", var7);
        }
    }
​
    this.processDeferredImportSelectors();
}
private void processDeferredImportSelectors() {
        List<ConfigurationClassParser.DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
        this.deferredImportSelectors = null;
        if (deferredImports != null) {
            deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
            Map<Object, ConfigurationClassParser.DeferredImportSelectorGrouping> groupings = new LinkedHashMap();
            Map<AnnotationMetadata, ConfigurationClass> configurationClasses = new HashMap();
            Iterator var4 = deferredImports.iterator();
​
            while(var4.hasNext()) {
                ConfigurationClassParser.DeferredImportSelectorHolder deferredImport = (ConfigurationClassParser.DeferredImportSelectorHolder)var4.next();
                Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();
                ConfigurationClassParser.DeferredImportSelectorGrouping grouping = (ConfigurationClassParser.DeferredImportSelectorGrouping)groupings.computeIfAbsent(group != null ? group : deferredImport, (key) -> {
                    return new ConfigurationClassParser.DeferredImportSelectorGrouping(this.createGroup(group));
                });
                grouping.add(deferredImport);
                configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(), deferredImport.getConfigurationClass());
            }
​
            var4 = groupings.values().iterator();
​
            while(var4.hasNext()) {
                ConfigurationClassParser.DeferredImportSelectorGrouping grouping = (ConfigurationClassParser.DeferredImportSelectorGrouping)var4.next();
                grouping.getImports().forEach((entry) -> {
                    ConfigurationClass configurationClass = (ConfigurationClass)configurationClasses.get(entry.getMetadata());
​
                    try {
                        this.processImports(configurationClass, this.asSourceClass(configurationClass), this.asSourceClasses(entry.getImportClassName()), false); //调用processImports方法
                    } catch (BeanDefinitionStoreException var5) {
                        throw var5;
                    } catch (Throwable var6) {
                        throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" + configurationClass.getMetadata().getClassName() + "]", var6);
                    }
                });
            }
​
        }
    }
private void processImports(ConfigurationClass configClass, ConfigurationClassParser.SourceClass currentSourceClass, Collection<ConfigurationClassParser.SourceClass> importCandidates, boolean checkForCircularImports) {
        if (!importCandidates.isEmpty()) {
            if (checkForCircularImports && this.isChainedImportOnStack(configClass)) {
                this.problemReporter.error(new ConfigurationClassParser.CircularImportProblem(configClass, this.importStack));
            } else {
                this.importStack.push(configClass);
​
                try {
                    Iterator var5 = importCandidates.iterator();
​
                    while(true) {
                        while(true) {
                            while(var5.hasNext()) {
                                ConfigurationClassParser.SourceClass candidate = (ConfigurationClassParser.SourceClass)var5.next();
                                Class candidateClass;
                                if (candidate.isAssignable(ImportSelector.class)) {
                                    candidateClass = candidate.loadClass();
                                    ImportSelector selector = (ImportSelector)BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
                                    ParserStrategyUtils.invokeAwareMethods(selector, this.environment, this.resourceLoader, this.registry);
                                    if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
                                        this.deferredImportSelectors.add(new ConfigurationClassParser.DeferredImportSelectorHolder(configClass, (DeferredImportSelector)selector));
                                    } else {
                                        String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata()); //执行@import类的selectImports方法;
                                        Collection<ConfigurationClassParser.SourceClass> importSourceClasses = this.asSourceClasses(importClassNames);
                                        this.processImports(configClass, currentSourceClass, importSourceClasses, false);
                                    }
                                } else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                                    candidateClass = candidate.loadClass();
                                    ImportBeanDefinitionRegistrar registrar = (ImportBeanDefinitionRegistrar)BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
                                    ParserStrategyUtils.invokeAwareMethods(registrar, this.environment, this.resourceLoader, this.registry);
                                    configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                                } else {
                                    this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                                    this.processConfigurationClass(candidate.asConfigClass(configClass));
                                }
                            }
​
                            return;
                        }
                    }
                } catch (BeanDefinitionStoreException var15) {
                    throw var15;
                } catch (Throwable var16) {
                    throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" + configClass.getMetadata().getClassName() + "]", var16);
                } finally {
                    this.importStack.pop();
                }
            }
        }
    }
​
// selectImports 的具体执行逻辑 注释参考https://blog.csdn.net/andy_zhang2007/article/details/78580980
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        try {
            // 从配置文件中加载 AutoConfigurationMetadata
            AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                    .loadMetadata(this.beanClassLoader);
            AnnotationAttributes attributes = getAttributes(annotationMetadata);
            // 获取所有候选配置类EnableAutoConfiguration
            // 使用了内部工具使用SpringFactoriesLoader,查找classpath上所有jar包中的
            // META-INF\spring.factories,找出其中key为
            // org.springframework.boot.autoconfigure.EnableAutoConfiguration 
            // 的属性定义的工厂类名称。
            // 虽然参数有annotationMetadata,attributes,但在 AutoConfigurationImportSelector 的
            // 实现 getCandidateConfigurations()中,这两个参数并未使用
            List<String> configurations = getCandidateConfigurations(annotationMetadata,
                    attributes);
            // 去重                   
            configurations = removeDuplicates(configurations);
            // 排序 : 先按字典序,再按order属性,再考虑注解  @AutoConfigureBefore @AutoConfigureAfter
            configurations = sort(configurations, autoConfigurationMetadata);
            // 应用 exclusion 属性
            Set<String> exclusions = getExclusions(annotationMetadata, attributes);
            checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            // 应用过滤器AutoConfigurationImportFilter,
            // 对于 spring boot autoconfigure,定义了一个需要被应用的过滤器 :
            // org.springframework.boot.autoconfigure.condition.OnClassCondition,
            // 此过滤器检查候选配置类上的注解@ConditionalOnClass,如果要求的类在classpath
            // 中不存在,则这个候选配置类会被排除掉
            configurations = filter(configurations, autoConfigurationMetadata);
            // 现在已经找到所有需要被应用的候选配置类
            // 广播事件 AutoConfigurationImportEvent
            fireAutoConfigurationImportEvents(configurations, exclusions);
            return configurations.toArray(new String[configurations.size()]);
        }
        catch (IOException ex) {
            throw new IllegalStateException(ex);
        }
    }
    /**
     * Return the auto-configuration class names that should be considered. By default
     * this method will load candidates using SpringFactoriesLoader with
     * getSpringFactoriesLoaderFactoryClass().
     * @param metadata the source metadata
     * @param attributes the getAttributes(AnnotationMetadata) annotation
     * attributes
     * @return a list of candidate configurations
     */
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
            AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
                getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
        Assert.notEmpty(configurations,
                "No auto configuration classes found in META-INF/spring.factories. If you "
                        + "are using a custom packaging, make sure that file is correct.");
        return configurations;
    }

    /**
     * Return the class used by SpringFactoriesLoader to load configuration
     * candidates.
     * @return the factory class
     */
    protected Class<?> getSpringFactoriesLoaderFactoryClass() {
        return EnableAutoConfiguration.class;
    }   
    /**
      * 根据autoConfigurationMetadata信息对候选配置类configurations进行过滤
      **/
    private List<String> filter(List<String> configurations,
            AutoConfigurationMetadata autoConfigurationMetadata) {
        long startTime = System.nanoTime();
        String[] candidates = configurations.toArray(new String[configurations.size()]);
        // 记录候选配置类是否需要被排除,skip为true表示需要被排除,全部初始化为false,不需要被排除
        boolean[] skip = new boolean[candidates.length];
        // 记录候选配置类中是否有任何一个候选配置类被忽略,初始化为false
        boolean skipped = false;
        // 获取AutoConfigurationImportFilter并逐个应用过滤
        for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) {
            // 对过滤器注入其需要Aware的信息
            invokeAwareMethods(filter);
            // 使用此过滤器检查候选配置类跟autoConfigurationMetadata的匹配情况
            boolean[] match = filter.match(candidates, autoConfigurationMetadata);
            for (int i = 0; i < match.length; i++) {
                if (!match[i]) {
                // 如果有某个候选配置类不符合当前过滤器,将其标记为需要被排除,
                // 并且将 skipped设置为true,表示发现了某个候选配置类需要被排除
                    skip[i] = true;
                    skipped = true;
                }
            }
        }
        if (!skipped) {
        // 如果所有的候选配置类都不需要被排除,则直接返回外部参数提供的候选配置类集合
            return configurations;
        }
        // 逻辑走到这里因为skipped为true,表明上面的的过滤器应用逻辑中发现了某些候选配置类
        // 需要被排除,这里排除那些需要被排除的候选配置类,将那些不需要被排除的候选配置类组成
        // 一个新的集合返回给调用者
        List<String> result = new ArrayList<String>(candidates.length);
        for (int i = 0; i < candidates.length; i++) {
            if (!skip[i]) {
                result.add(candidates[i]);
            }
        }
        if (logger.isTraceEnabled()) {
            int numberFiltered = configurations.size() - result.size();
            logger.trace("Filtered " + numberFiltered + " auto configuration class in "
                    + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime)
                    + " ms");
        }
        return new ArrayList<String>(result);
    }   
    /**
      * 使用内部工具 SpringFactoriesLoader,查找classpath上所有jar包中的
      * META-INF\spring.factories,找出其中key为
      * org.springframework.boot.autoconfigure.AutoConfigurationImportFilter 
      * 的属性定义的过滤器类并实例化。
      * AutoConfigurationImportFilter过滤器可以被注册到 spring.factories用于对自动配置类
      * 做一些限制,在这些自动配置类的字节码被读取之前做快速排除处理。
      * spring boot autoconfigure 缺省注册了一个 AutoConfigurationImportFilter :
      * org.springframework.boot.autoconfigure.condition.OnClassCondition
    **/
    protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
        return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class,
                this.beanClassLoader);
    }   
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
    return configurations;
}
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
    String factoryClassName = factoryClass.getName();
    return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
    if (result != null) {
        return result;
    } else {
        try {
            Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
            LinkedMultiValueMap result = new LinkedMultiValueMap();
​
            while(urls.hasMoreElements()) {
                URL url = (URL)urls.nextElement();
                UrlResource resource = new UrlResource(url);
                Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                Iterator var6 = properties.entrySet().iterator();
​
                while(var6.hasNext()) {
                    Entry<?, ?> entry = (Entry)var6.next();
                    List<String> factoryClassNames = Arrays.asList(StringUtils.commaDelimitedListToStringArray((String)entry.getValue()));
                    result.addAll((String)entry.getKey(), factoryClassNames);
                }
            }
​
            cache.put(classLoader, result);
            return result;
        } catch (IOException var9) {
            throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var9);
        }
    }
}

而loadSpringFactories会扫描所有jar包下的 META‐INF/spring.factories文件,并封装成properties属性对象;并以key-value的形式存放在MultiValueMap对象中,List configurations = getCandidateConfigurations(annotationMetadata, attributes);获取候选的配置时,只需要获取key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的list保存的value,然后返回到processImports方法中,最终注册到IOC容器中;整个自动配置结束;

参考:https://blog.csdn.net/zero__007/article/details/80386239

猜你喜欢

转载自blog.csdn.net/Java_Jsp_Ssh/article/details/81545716