SpringBoot源碼-@Configuration註解的解析

1. 簡介

本篇文章是對上一篇文章Spring刷新應用上下文的補充說明,詳細講述了上一篇文章中的第五步(實例化並調用全部註冊的beanFactory後置處理器)中Spring解析@Configuration註解的過程。java

在Spring3.0以前的Spring核心框架中,咱們啓動一個Spring容器必須使用一個XML文件。而到了3.0以後的版本Spring爲建立容器新增了一個入口類——AnnotationConfigApplicationContext。AnnotationConfigApplicationContext和過去的ClassPathXmlApplicationContext、FileSystemXmlApplicationContext等方法不一樣的是他不用再指定任何XML配置文件,而是能夠經過指定類向容器添加Bean。web

所以,從Spring3.0後,只要在配置類上加@Configuration註解就能夠替換以前的xml配置文件,被註解的類內部包含有一個或多個被@Bean註解的方法,這些方法將會被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext類進行掃描,並用於構建bean定義,初始化Spring容器。從使用的角度來講能夠把他理解爲XML配置中的<beans>標籤,可是兩者又有些細節的差別。在<beans>標籤中除了使用<bean>聲名Bean之外,還有各類<context>標籤來擴展功能,好比<context:component-scan/>、<context:annotation-config />以及<import>等,這些擴展的功能並非@Configuration註解的參數,而是經過其它註解來實現的如:@ComponentScan、@Import。spring

1.1 前提

使用@Configuration註解需知足如下要求express

  1. @Configuration不能夠是final類型;
  2. @Configuration不能夠是匿名類;
  3. 嵌套的configuration必須是靜態類。

1.2 聲明

Spring對@Configuration註解類的解析最終是在ConfigurationClassPostProcessor類調用的processConfigBeanDefinitions方法中使用Spring的工具類ConfigurationClassParser來進行的。ConfigurationClassPostProcessor類是BeanFactoryPostProcessor的實現(看下圖),BeanFactoryPostProcessor用於spring應用啓動過程當中@Configuration類的處理(發現和處理全部的配置類,註冊其中的bean定義)。segmentfault

clipboard.png

1.3 @Configuration源碼

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    @AliasFor(annotation = Component.class)
    String value() default ""; //能夠自定義Bean的名稱
}

2 @Configuration類的解析

介紹
ConfigurationClassPostProcessor 位於 org.springframework.context.annotation 包中,這是一個 BeanDefinitionRegistryPostProcessor,隱含地也實現了接口BeanFactoryPostProcessor,用於spring 應用啓動過程當中 @Configuration 類的處理(發現和處理全部的配置類,註冊其中的bean定義)。緩存

引入時機app

  • 非Springboot的Sping應用,當在配置文件中使用<context:annotation-config/>或者 <context:component-scan/>時,該BeanFactoryPostProcessor會被註冊。
  • Springboot 應用中在ApplicationContext對象建立時,會在應用上下文類(參考AnnotationConfigServletWebServerApplicationContext/AnnotationConfigReactiveWebServerApplicationContext)的構造函數中建立AnnotatedBeanDefinitionReader對象時調用 AnnotationConfigUtils.registerAnnotationConfigProcessors() 註冊這個BeanFactoryPostProcessor到容器。

調用時機
ConfigurationClassPostProcessor既實現了BeanDefinitionRegistryPostProcessor定義的方法postProcessBeanDefinitionRegistry,也實現了接口BeanFactoryPostProcessor定義的方法postProcessBeanFactory。框架

AbstractApplicationContext.refresh()方法執行時,在BeanFactory,也就是Spring容器被準備(prepare)和postProcess以後,AbstractApplicationContext的invokeBeanFactoryPostProcessors()方法被調用,這個方法用來執行全部容器中被做爲bean註冊的BeanFactoryPostProcessor,其中就包括對ConfigurationClassPostProcessor方法postProcessBeanDefinitionRegistry()以及postProcessBeanFactory()方法的調用。ide

調用過程
解析過程是在容器刷新方法中--refreshContext(context) --> refresh(context) --> ApplicationContext.refresh()
--> invokeBeanFactoryPostProcessor(beanFactory)(該方法在容器刷新專欄有詳細講解,就是調用了PostProcessorRegistrationDelegate類的invokeBeanFactoryPostProcessors方法)這個方法調用全部的BeanFactoryPostProcessor,同時也就啓動了Configuration類的解析。此時的BeanFactory中已經加載了main class,以及內部定義的class。內部定義的class都是帶internal的,這些並非Configuration Class,解析程序會忽略這些類,最後只有SpringBoot的啓動類(如:DemoApplication)會進行Configuration的解析處理。函數

這裏之全部這樣作的緣由是上述方法執行時有可能註冊新的BeanDefinitionRegistryPostProcessor/BeanFactoryPostProcessor到容器,而這些新註冊的BeanDefinitionRegistryPostProcessor/BeanFactoryPostProcessor也須要在這個階段執行。

注意事項

  • BeanDefinitionRegistryPostProcessor可能會註冊另一個BeanDefinitionRegistryPostProcessor。
  • 一個非BeanDefinitionRegistryPostProcessor BeanFactoryPostProcessor可能會註冊另一個BeanFactoryPostProcessor。
  • 一個非BeanDefinitionRegistryPostProcessor BeanFactoryPostProcessor不會註冊另一個BeanDefinitionRegistryPostProcessor(註冊了可是不會被執行)。

由於配置類中定義的每一個bean定義方法都必需要趕在其它BeanFactoryPostProcessor應用前,因此完成bean定義註冊任務的ConfigurationClassPostProcessor 被設計爲擁有最高執行優先級Ordered.HIGHEST_PRECEDENCE。

2.1 開始看代碼

重提上一篇文章Spring 刷新應用上下文中的invokeBeanFactoryPostProcessors方法,用以引出下文。

//實例化並調用全部註冊的beanFactory後置處理器
public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

        Set<String> processedBeans = new HashSet<>();

        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();
            //遍歷全部的beanFactoryPostProcessors,
            //將BeanDefinitionRegistryPostProcessor和普通BeanFactoryPostProcessor區分開
            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                   //主要看這裏!!!
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }
                else {
                    regularPostProcessors.add(postProcessor);
                }
            }
            ....省略此處代碼在以前的文章已經介紹過了

該方法主要作了如下事情:

  • 執行了BeanDefinitionRegistryPostProcessor(此處只有ConfigurationClassPostProcessor)
  • 執行了BeanFactoryPostProcessor
  • 完成了@Configuration配置文件的解析,而且把掃描到的、配置的Bean定義信息都加載進容器裏
  • Full模式下,完成了對@Configuration配置文件的增強,使得管理Bean依賴關係更加的方便了

registryProcessor.postProcessBeanDefinitionRegistry(registry)這一步(調用了ConfigurationClassPostProcessor類的postProcessBeanDefinitionRegistry方法)使用工具ConfigurationClassParser嘗試發現全部的配置(@Configuration)類,使用工具ConfigurationClassBeanDefinitionReader註冊所發現的配置類中全部的bean定義。結束執行的條件是全部配置類都被發現和處理,相應的bean定義註冊到容器。

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
        PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {

2.2 主要看這裏

下面看ConfigurationClassPostProcessor類中postProcessBeanDefinitionRegistry()的處理邏輯,該方法使用工具ConfigurationClassParser嘗試發現全部的配置(@Configuration)類,使用工具ConfigurationClassBeanDefinitionReader註冊所發現的配置類中全部的bean定義。結束執行的條件是全部配置類都被發現和處理,相應的bean定義註冊到容器。

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        //根據BeanDefinitionRegistry,生成registryId 是全局惟一的。
        int registryId = System.identityHashCode(registry);
        // 判斷,若是這個registryId 已經被執行過了,就不可以再執行了,不然拋出異常
        if (this.registriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException(
                    "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
        }
        if (this.factoriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException(
                    "postProcessBeanFactory already called on this post-processor against " + registry);
        }
        // 已經執行過的registry防止重複執行
        this.registriesPostProcessed.add(registryId);
        // 調用processConfigBeanDefinitions 進行Bean定義的加載
        processConfigBeanDefinitions(registry);
    }

2.2.1 處理配置類並註冊BeanDefinition

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        // 記錄候選配置類
        List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
        // 獲取已經註冊的bean名稱(將容器中已經登記的Bean定義做爲候選配置類名稱)
        String[] candidateNames = registry.getBeanDefinitionNames();
        // 程序此時處於容器啓動的早期,一般此時 candidateNames 中實際上只會有一個配置類(即...Application啓動類)
        for (String beanName : candidateNames) {
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
            //若是beanDef如今就已經肯定了是full或者lite,說明已經被解析過了,因此再來就直接輸出debug
            if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
                    ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                }
            }
            // 檢查是不是@Configuration的Class,若是是就標記下屬性:full 或者lite。                                       
            else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                //若是當前的bean是Javabean配置類(含有@Configuration註解的類),則加入到集合configCandidates中
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }

        // 若是一個配置文件類都沒找到,直接返回
        if (configCandidates.isEmpty()) {
            return;
        }
        // 把這些配置按照@Order註解進行排序(@Configuration註解的配置文件是支持order排序的。可是普通bean不行)
        configCandidates.sort((bd1, bd2) -> {
            int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
            int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
            return Integer.compare(i1, i2);
        });

       // 嘗試檢測自定義的 BeanNameGenerator
        SingletonBeanRegistry sbr = null;
        if (registry instanceof SingletonBeanRegistry) {
            sbr = (SingletonBeanRegistry) registry;
            if (!this.localBeanNameGeneratorSet) {
                BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
                if (generator != null) {
                    this.componentScanBeanNameGenerator = generator;
                    this.importBeanNameGenerator = generator;
                }
            }
        }
        // web環境這裏都設置了StandardServletEnvironment
        //正常狀況下env環境不可能爲null(此處作容錯處理)
        if (this.environment == null) {
            this.environment = new StandardEnvironment();
        }

        // ConfigurationClassParser是真正解析@Configuration註解的類
        ConfigurationClassParser parser = new ConfigurationClassParser(
                this.metadataReaderFactory, this.problemReporter, this.environment,
                this.resourceLoader, this.componentScanBeanNameGenerator, registry);
        
        // 表示將要被處理的候選配置類
        // 由於不清楚候選是否確實是配置類,因此使用BeanDefinitionHolder類型記錄
        // 這裏初始化爲方法開始時容器中註解了@Configuration的Bean定義的集合
        Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
        // 裝載已經處理過的配置類,最大長度爲:configCandidates.size()
        // 表示已經處理的配置類,已經被處理的配置類已經明確了其類型,因此用 ConfigurationClass 類型記錄,
        Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
        do {
           // 解析目標配置類【第一個解析的是應用程序主類】
            parser.parse(candidates);
            // 主要校驗配置類不能使用final修飾符(CGLIB代理是生成一個子類,所以原先的類不能使用final修飾)
            parser.validate();
            // 從分析器parser中獲取分析獲得的配置類configurationClasses
            Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
            configClasses.removeAll(alreadyParsed);

            // 若是Reader爲null,那就實例化ConfigurationClassBeanDefinitionReader來加載Bean,
           // 並加入到alreadyParsed中,用於去重(避免@ComponentScan直接互掃)
            if (this.reader == null) {
                this.reader = new ConfigurationClassBeanDefinitionReader(
                        registry, this.sourceExtractor, this.resourceLoader, this.environment,
                        this.importBeanNameGenerator, parser.getImportRegistry());
            }
            // 此處調用ConfigurationClassBeanDefinitionReader的loadBeanDefinitionsd方法
            // 加載配置文件裏面的@Bean/@Import,此方法決定了向容器註冊Bean定義信息的順序
            this.reader.loadBeanDefinitions(configClasses);
            // 剛剛處理完的配置類記錄到已處理配置類alreadyParsed集合中
            alreadyParsed.addAll(configClasses);
            // 清空候選配置類集合,爲下一輪do循環作初始化準備
            candidates.clear();
            // 若是registry中註冊的bean的數量 大於 以前得到的數量
            if (registry.getBeanDefinitionCount() > candidateNames.length) {
                // 則意味着在解析過程當中發現並註冊了更多的Bean定義到容器中去,這些新註冊的Bean定義
                // 也有多是候選配置類,它們也要被處理用來發現和註冊Bean定義
               String[] newCandidateNames = registry.getBeanDefinitionNames();
                Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
                Set<String> alreadyParsedClasses = new HashSet<>();
                for (ConfigurationClass configurationClass : alreadyParsed) {
                    alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
                }
                for (String candidateName : newCandidateNames) {
                   // 若是老的oldCandidateNames不包含就說明是新進來的候選的Bean定義(即當前 BeanDefinition 是新解析的)
                    if (!oldCandidateNames.contains(candidateName)) {
                        BeanDefinition bd = registry.getBeanDefinition(candidateName);
                        if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                                !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                              // 基於 BeanDefinition 建立 BeanDefinitionHolder 並將其寫入 candidates
                            candidates.add(new BeanDefinitionHolder(bd, candidateName));
                        }
                    }
                }
                candidateNames = newCandidateNames;
            }
        }
        while (!candidates.isEmpty());// 直到全部的配置類都解析完畢
        // 註冊 ImportRegistry bean 到 SingletonBeanRegistry 中
        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();
        }
    }

下面文章主要圍繞processConfigBeanDefinitions方法作的擴展延伸。

3 解析processConfigBeanDefinitions方法

3.1 概要分析

處理配置類並註冊BeanDefinition的方法比較複雜,下面針對方法中一些重要的功能點進行解析:
3.2. 介紹ConfigurationClassUtils工具類
3.3. 解析Java配置類ConfigurationClassParser#parse(Set<BeanDefinitionHolder> configCandidates)

3.3.1 processConfigurationClass解析單個配置類
        3.3.1.1 doProcessConfigurationClass
            3.3.1.1.1 processMemberClasses
            3.3.1.1.2 處理給定的@PropertySource 註解元數據
            3.3.1.1.3 @ComponentScan註解解析過程
            3.3.1.1.3 processImports
            3.3.1.1.5 processInterfaces
        3.3.1.2 ConditionEvaluator條件評估
        3.3.1.3 ConfigurationClass配置類
        3.3.1.4 ConditionalOnProperty

3.4. loadBeanDefinitions加載bean定義信息

3.2 ConfigurationClassUtils工具類

ConfigurationClassUtils工具類用於檢查是不是含有@Configuration註解的類,須要注意下面兩個核心方法,是如何判斷某個類是否爲配置類的(判斷是full模式,仍是lite模式的配置文件):

  • 若是類上有@Configuration註解說明是一個徹底(Full)的配置類
  • 若是若是類上面有@Component,@ComponentScan,@Import,@ImportResource這些註解,那麼就是一個簡化配置類。若是不是上面兩種狀況,那麼有@Bean註解修飾的方法也是簡化配置類
abstract class ConfigurationClassUtils {

    private static final String CONFIGURATION_CLASS_FULL = "full";

    private static final String CONFIGURATION_CLASS_LITE = "lite";
    private static final String CONFIGURATION_CLASS_ATTRIBUTE =
            Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "configurationClass");

    private static final String ORDER_ATTRIBUTE =
            Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "order");

    private static final Log logger = LogFactory.getLog(ConfigurationClassUtils.class);

    private static final Set<String> candidateIndicators = new HashSet<>(4);

    static {
        candidateIndicators.add(Component.class.getName());
        candidateIndicators.add(ComponentScan.class.getName());
        candidateIndicators.add(Import.class.getName());
        candidateIndicators.add(ImportResource.class.getName());
    }
    
    // 只要這個類標註了:@Configuration註解就行(接口、抽象類都沒問題)
    public static boolean isFullConfigurationCandidate(AnnotationMetadata metadata) {
        return metadata.isAnnotated(Configuration.class.getName());
    }
    
    // 判斷是Lite模式的條件:(首先確定沒有@Configuration註解)
    // 一、不能是接口
    // 二、但凡只要標註了一個下面註解,都算lite模式:@Component @ComponentScan @Import @ImportResource
    // 三、只要存在有一個方法標註了@Bean註解,那就是lite模式
    public static boolean isLiteConfigurationCandidate(AnnotationMetadata metadata) {
        // 不能是接口
        if (metadata.isInterface()) {
            return false;
        }

        // 但凡只有標註了一個下面註解,都算lite模式:@Component @ComponentScan @Import @ImportResource
        for (String indicator : candidateIndicators) {
            if (metadata.isAnnotated(indicator)) {
                return true;
            }
        }

        // 只有存在有一個方法標註了@Bean註解,那就是lite模式
        try {
            return metadata.hasAnnotatedMethods(Bean.class.getName());
        }
        catch (Throwable ex) {
            if (logger.isDebugEnabled()) {
                logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
            }
            return false;
        }
    }
    // 無論是Full模式仍是Lite模式,都被認爲是候選的配置類,是上面兩個方法的結合
    public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
        return (isFullConfigurationCandidate(metadata) || isLiteConfigurationCandidate(metadata));
    }
    
    // 下面兩個方法是直接判斷Bean定義信息,是不是配置類,至於Bean定義裏這個屬性何時放進去的,請參考
    //ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)方法,
    //它會對每一個Bean定義信息進行檢測(畢竟剛開始Bean定義信息是很是少的,因此速度也很快)
    public static boolean isFullConfigurationClass(BeanDefinition beanDef) {
        return CONFIGURATION_CLASS_FULL.equals(beanDef.getAttribute(CONFIGURATION_CLASS_ATTRIBUTE));
    }

    public static boolean isLiteConfigurationClass(BeanDefinition beanDef) {
        return CONFIGURATION_CLASS_LITE.equals(beanDef.getAttribute(CONFIGURATION_CLASS_ATTRIBUTE));
    }

Full模式和Lite模式的區別:

  • 當@Bean方法聲明在沒有被@Conguration註解的類裏,這就是所謂的以’精簡’模式(Lite)處理。例如,在一個@Component中,甚至在一個普通的類中聲明的bean方法都會以’精簡’處理。
  • 跟完整@Configuration不一樣的是,精簡@Bean方法難以聲明bean之間的依賴。一般,在精簡模式中操做時,不該該在一個@Bean方法中調用另外一個@Bean方法。一種推薦的方式是隻在@Configuration類中使用@Bean方法,這樣能夠確保老是使用’完整’模式,避免@Bean方法意外地被調用屢次,減小那些在精簡模式下產生的很難跟蹤的微妙bugs。

例如:

@Configuration 
public class AppConfig {

    @Bean
    public Foo foo() {
        return new Foo(bar()); // 這裏調用的bar()方法
    }
    @Bean
    public Bar bar() {
        return new Bar();
    }
}

Foo 接受一個bar的引用來進行構造器注入:這種方法聲明的bean的依賴關係只有在@Configuration類的@Bean方法中有效。若是換成@Component(Lite模式),則foo()方法中new Foo(bar())傳入的bar()方法會每次產生一個新的Bar對象

結論:
在@Component或其餘組建中使用@Bean好處是不會啓動CGLIB這種重量級工具(不過在Spring中即便這裏不使用,其餘不少地方也在使用)。而且@Component及其相關的Stereotype組件自身就有摸框級別的功能,在這裏使用@Bean註解能很好的代表一個Bean的從屬和結構關係,可是須要注意直接調用方法的「反作用」。

我的建議若是沒什麼特別的要求就使用@Configuration,引入CGLIB並不會影響多少性能,然而坑會少不少。在spring官網將用@Configuration建立的@Bean稱呼爲"Full"模式、將@Component建立的@Bean稱呼爲"'lite"模式,從字面上也能略知他們的差別。

只有類上標註@Configuration纔是full模式。標註有@Component、@ComponentScan、@Import、@ImportResource或者啥註解都沒標註可是有被標註了@Bean的方法這種也是lite模式

3.3 解析Java配置類

解過程當中

  1. 若是遇到註解了@Component類,直接做爲Bean定義註冊到容器
  2. 若是註解或者註解的註解中有@Import, 處理全部這些@import,識別配置類,添加到分析器的屬性configurationClasses中去

ConfigurationClassParser#parse

public void parse(Set<BeanDefinitionHolder> configCandidates) {
        this.deferredImportSelectors = new LinkedList<>();
        
        for (BeanDefinitionHolder holder : configCandidates) {
            BeanDefinition bd = holder.getBeanDefinition();
           // 下面三種方式解析Bean
            try {
            // 咱們使用的註解驅動,因此會到這個parse進來處理。
                if (bd instanceof AnnotatedBeanDefinition) {
                    // 其實內部調用都是processConfigurationClass進行解析的
                    parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
                }
                //只要有註解標註的,都會走這裏來解析
                else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
                    parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
                }
                else {
                    parse(bd.getBeanClassName(), holder.getBeanName());
                }
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                        "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
            }
        }
        //處理ImportSelect,執行找到的 DeferredImportSelector 
        //DeferredImportSelector 是 ImportSelector 的一個變種。
        // ImportSelector 被設計成其實和@Import註解的類一樣的導入效果,可是實現 ImportSelector
        // 的類能夠條件性地決定導入哪些配置。
        // DeferredImportSelector 的設計目的是在全部其餘的配置類被處理後才處理。這也正是
        // 該語句被放到本函數最後一行的緣由。
        processDeferredImportSelectors();
    }

該方法作了三件事以下:

  1. 實例化deferredImportSelectors
  2. 遍歷configCandidates ,進行處理.根據BeanDefinition 的類型 作不一樣的處理,通常都會調用ConfigurationClassParser#parse 進行解析
  3. 處理ImportSelect

3.3.1 處理@Configuration配置類

解析@Configuration配置文件,而後加載進Bean的定義信息。能夠看到它加載Bean定義信息的一個順序

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
        //ConfigurationCondition繼承自Condition接口
        // ConfigurationPhase枚舉類型的做用:根據條件來判斷是否加載這個配置類
        // 兩個值:PARSE_CONFIGURATION 若條件不匹配就不加載此@Configuration
        // REGISTER_BEAN:不管如何,全部@Configurations都將被解析。
        if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
            return;
        }
        
        //判斷同一個配置類是否重複加載過,若是重複加載過
        ConfigurationClass existingClass = this.configurationClasses.get(configClass);
        if (existingClass != null) {
            if (configClass.isImported()) {
                //若是這個配置類已經存在了,後面又被@Import進來了就會走這裏,而後作屬性合併
                if (existingClass.isImported()) {
                    existingClass.mergeImportedBy(configClass);
                }
                return;
            }
            else {
                //從集合中移除舊的配置類,後續邏輯將處理新的配置 
                this.configurationClasses.remove(configClass);
                this.knownSuperclasses.values().removeIf(configClass::equals);
            }
        }

        SourceClass sourceClass = asSourceClass(configClass);
        do {
            //【doProcessConfigurationClass】這個方法是解析配置文件的核心方法
            sourceClass = doProcessConfigurationClass(configClass, sourceClass);
        }
        while (sourceClass != null);
        //保存咱們全部的配置類(注意:它是一個LinkedHashMap,因此是有序的和bean定義信息息息相關)
        this.configurationClasses.put(configClass, configClass);
    }

3.3.1.1 doProcessConfigurationClass

doProcessConfigurationClass方法主要實現從配置類中解析全部bean,包括處理內部類,父類以及各類註解

@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
        throws IOException {
    //配置類上存在 Component註解,則嘗試遞歸處理其內部成員類
    if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
        processMemberClasses(configClass, sourceClass);
    }

    //處理全部 @PropertySource 註解:將目標資源導入到 environment.propertySources 中
    //將全部的 @PropertySource 註解合併到 @PropertySources 註解中,並逐個進行處理
    for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
            sourceClass.getMetadata(), PropertySources.class,
            org.springframework.context.annotation.PropertySource.class)) {
        if (this.environment instanceof ConfigurableEnvironment) {
            processPropertySource(propertySource);
        }
        else {
            logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                    "]. Reason: Environment must implement ConfigurableEnvironment");
        }
    }

    //處理全部的 ComponentScan 註解
    //以深度優先的方式遞歸處理全部掃描到的配置類
    Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
            sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    if (!componentScans.isEmpty() &&
            !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
         //循環處理每一個 ComponentScan 註解
        for (AnnotationAttributes componentScan : componentScans) {
            //若是此配置類存在ComponentScan註解,則經過 ComponentScanAnnotationParser當即處理它
            Set<BeanDefinitionHolder> scannedBeanDefinitions =
                    this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
            // 遍歷掃描到的全部組件
            for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
            //若果掃描出的bean定義是配置類(含有@COnfiguration)
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(
                        holder.getBeanDefinition(), this.metadataReaderFactory)) {
                    //繼續調用parse,內部再次調用doProcessConfigurationClas()遞歸解析
                    parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
                }
            }
        }
    }

    //處理全部的 @Import 註解
    //1.優先處理全部註解上的 @Import 註解導入的配置類
    //2.後處理此類上經過@Import 註解直接導入的配置類
    processImports(configClass, sourceClass, getImports(sourceClass), true);

    //處理@ImportResource註解
    AnnotationAttributes importResource =
            AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
    if (importResource != null) {
        // 讀取資源位置
        String[] resources = importResource.getStringArray("locations");
        // 讀取 BeanDefinitionReader
        Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
        for (String resource : resources) {
             // 解析佔位符
            String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
             // 寫入緩存
            configClass.addImportedResource(resolvedResource, readerClass);
        }
    }

    //處理全部的 @Bean 方法,將它們解析爲 BeanMethod 並寫入配置類中
    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    for (MethodMetadata methodMetadata : beanMethods) {
        //將解析出的全部@Bean註解方法添加到configClass配置類信息中
        configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    }
    
    //處理全部接口上非 Abstract 的 @Bean 方法,並添加到configClass配置類信息中
    processInterfaces(configClass, sourceClass);

    // 若是有父類,則返回父類,遞歸執行doProcessConfigurationClass()解析父類
    if (sourceClass.getMetadata().hasSuperClass()) {
        String superclass = sourceClass.getMetadata().getSuperClassName();
        if (superclass != null && !superclass.startsWith("java") &&
                !this.knownSuperclasses.containsKey(superclass)) {
            // 已處理的父類緩存
            this.knownSuperclasses.put(superclass, configClass);
            return sourceClass.getSuperClass();
        }
    }
     // 此配置類處理完成
    return null;
}
3.3.1.1.1 processMemberClasses
private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
        // 讀取全部的成員類
        Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
         // 存在成員類
        if (!memberClasses.isEmpty()) {
            List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
            for (SourceClass memberClass : memberClasses) {
                  // 過濾出全部的配置類
                if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
                        !memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
                    candidates.add(memberClass);
                }
            }
            // 根據 Order 進行排序
            OrderComparator.sort(candidates);
            for (SourceClass candidate : candidates) {
                // 出現配置類循環導入
                if (this.importStack.contains(configClass)) {
                    this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
                }
                else {
                   //將此配置類入棧
                    this.importStack.push(configClass);
                    try {
                       // 處理此配置類
                        processConfigurationClass(candidate.asConfigClass(configClass));
                    }
                    finally {
                       //解析完成後將其出棧
                        this.importStack.pop();
                    }
                }
            }
        }
    }
3.3.1.1.2 處理給定的@PropertySource 註解元數據
private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
        // 讀取名稱
        String name = propertySource.getString("name");
        if (!StringUtils.hasLength(name)) {
            name = null;
        }
        // 讀取編碼
        String encoding = propertySource.getString("encoding");
        if (!StringUtils.hasLength(encoding)) {
            encoding = null;
        }
        // 讀取資源位置
        String[] locations = propertySource.getStringArray("value");
        Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
        // 讀取資源未找到則忽略標識
        boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
       // 讀取 PropertySourceFactory
        Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
        PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
                DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
        // 循環處理每一個資源
        for (String location : locations) {
            try {
               // 解析佔位符
                String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
                 // 讀取資源
               Resource resource = this.resourceLoader.getResource(resolvedLocation);
                 // 建立 ResourcePropertySource 並加入到 environment 中
               addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
            }
            catch (IllegalArgumentException | FileNotFoundException | UnknownHostException ex) {
                 // 佔位符解析失敗或資源未找到
                if (ignoreResourceNotFound) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
                    }
                }
                else {
                    throw ex;
                }
            }
        }
    }
3.3.1.1.3 @ComponentScan註解解析過程

@ComponentScan註解解析經過調用ComponentScanAnnotationParser的parse方法完成,而parse()方法內部處理了一些scanner屬性(過濾器設置)和basePackages包名處理,最終經過調用ClassPathBeanDefinitionScanner.doScan方法實現掃面工做。

3.3.1.1.3.1 ComponentScan 註解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    /**
     *  基礎包名稱
     */
    @AliasFor("basePackages")
    String[] value() default {};

    /**
     *  基礎包名稱
     */
    @AliasFor("value")
    String[] basePackages() default {};

    /**
     *  基礎包類【讀取指定類所在的包路徑】
     */
    Class<?>[] basePackageClasses() default {};

    /**
     *  用於生成 bean 名稱的 BeanNameGenerator
     */
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    /**
     *  範圍解析器
     */
    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

    /**
     *  是否須要爲目標組件生成代理,默認不生成
     */
    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

    /**
     *  資源模式
     */
    String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;

    /**
     *  是否使用默認的過濾器
     *  自動檢測 @Component、@Repository、@Service、@Controller 註解標註的類
     */
    boolean useDefaultFilters() default true;

    /**
     *  指定掃描哪些類型
     */
    Filter[] includeFilters() default {};

    /**
     *  指定排除哪些類型
     */
    Filter[] excludeFilters() default {};

    /**
     *  掃描到的單例 bean 是否須要延遲初始化
     */
    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    @interface Filter {
        /**
         *  過濾類型,默認是基於註解
         */
        FilterType type() default FilterType.ANNOTATION;

        /**
         *  用做篩選器的類,多個類之間是邏輯或的關係
         */
        @AliasFor("classes")
        Class<?>[] value() default {};

        /**
         *  用做篩選器的類,多個類之間是邏輯或的關係
         */
        @AliasFor("value")
        Class<?>[] classes() default {};

        /**
         *  匹配模式,根據 FilterType 分流
         */
        String[] pattern() default {};
    }
}
3.3.1.1.3.2 ComponentScan 註解解析器
/**
 *  @ComponentScan 註解解析器
 */
class ComponentScanAnnotationParser {
    private final Environment environment;
    private final ResourceLoader resourceLoader;
    private final BeanNameGenerator beanNameGenerator;
    private final BeanDefinitionRegistry registry;

    public ComponentScanAnnotationParser(Environment environment, ResourceLoader resourceLoader,
            BeanNameGenerator beanNameGenerator, BeanDefinitionRegistry registry) {
        this.environment = environment;
        this.resourceLoader = resourceLoader;
        this.beanNameGenerator = beanNameGenerator;
        this.registry = registry;
    }

    /**
     *  解析指定的 @ComponentScan 註解
     */
    public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
        // 類路徑 BeanDefinition 掃描器
        final ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry,
                componentScan.getBoolean("useDefaultFilters"), environment, resourceLoader);
        // 設置掃描器的 BeanNameGenerator
        final Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
        final boolean useInheritedGenerator = BeanNameGenerator.class == generatorClass;
        scanner.setBeanNameGenerator(useInheritedGenerator ? beanNameGenerator :
            BeanUtils.instantiateClass(generatorClass));
        // 嘗試設置掃描器的 ScopedProxyMode
        final ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
        if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
            scanner.setScopedProxyMode(scopedProxyMode);
        }
        else {
            final Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
            scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
        }
        // 設置掃描器的資源模式
        scanner.setResourcePattern(componentScan.getString("resourcePattern"));

        // 添加包含過濾器,默認無
        for (final AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
            for (final TypeFilter typeFilter : typeFiltersFor(filter)) {
                scanner.addIncludeFilter(typeFilter);
            }
        }
        // 添加排序過濾器
        for (final AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
            for (final TypeFilter typeFilter : typeFiltersFor(filter)) {
                scanner.addExcludeFilter(typeFilter);
            }
        }
        // 設置延遲初始化屬性
        final boolean lazyInit = componentScan.getBoolean("lazyInit");
        if (lazyInit) {
            scanner.getBeanDefinitionDefaults().setLazyInit(true);
        }

        final Set<String> basePackages = new LinkedHashSet<>();
        // 嘗試讀取 basePackages 屬性
        final String[] basePackagesArray = componentScan.getStringArray("basePackages");
        for (final String pkg : basePackagesArray) {
            // 解析佔位符,並按照 ,;\t\n 切割包路徑
            final String[] tokenized = StringUtils.tokenizeToStringArray(environment.resolvePlaceholders(pkg),
                    ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
            Collections.addAll(basePackages, tokenized);
        }
        // 讀取 basePackageClasses,並提取出包路徑
        for (final Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
            basePackages.add(ClassUtils.getPackageName(clazz));
        }
        /**
         *  若是 basePackages 和 basePackageClasses 都未配置,
         *  則以 @ComponentScan 註解所在配置類的包路徑做爲基礎包
         */
        if (basePackages.isEmpty()) {
            basePackages.add(ClassUtils.getPackageName(declaringClass));
        }

        // 忽略此配置類
        scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
            @Override
            protected boolean matchClassName(String className) {
                return declaringClass.equals(className);
            }
        });
        // 執行包掃描
        return scanner.doScan(StringUtils.toStringArray(basePackages));
    }

    private List<TypeFilter> typeFiltersFor(AnnotationAttributes filterAttributes) {
        final List<TypeFilter> typeFilters = new ArrayList<>();
        // 讀取過濾類型
        final FilterType filterType = filterAttributes.getEnum("type");
        // 讀取全部的 classes
        for (final Class<?> filterClass : filterAttributes.getClassArray("classes")) {
            switch (filterType) {
                // 1)過濾類型爲基於註解
                case ANNOTATION:
                    // 目標 class 是不是註解
                    Assert.isAssignable(Annotation.class, filterClass,
                            "@ComponentScan ANNOTATION type filter requires an annotation type");
                    @SuppressWarnings("unchecked") final
                    Class<Annotation> annotationType = (Class<Annotation>) filterClass;
                    // 添加註解類型過濾器
                    typeFilters.add(new AnnotationTypeFilter(annotationType));
                    break;
                    // 2)過濾類型爲基於目標類型及其子類
                case ASSIGNABLE_TYPE:
                    // 添加類型過濾器
                    typeFilters.add(new AssignableTypeFilter(filterClass));
                    break;
                    // 3)過濾類型爲基於自定義過濾器
                case CUSTOM:
                    // 添加自定義 TypeFilter
                    Assert.isAssignable(TypeFilter.class, filterClass,
                            "@ComponentScan CUSTOM type filter requires a TypeFilter implementation");
                    final TypeFilter filter = BeanUtils.instantiateClass(filterClass, TypeFilter.class);
                    ParserStrategyUtils.invokeAwareMethods(
                            filter, environment, resourceLoader, registry);
                    typeFilters.add(filter);
                    break;
                default:
                    throw new IllegalArgumentException("Filter type not supported with Class value: " + filterType);
            }
        }

        // 若是指定了匹配模式
        for (final String expression : filterAttributes.getStringArray("pattern")) {
            switch (filterType) {
                // 過濾類型爲 ASPECTJ
                case ASPECTJ:
                    typeFilters.add(new AspectJTypeFilter(expression, resourceLoader.getClassLoader()));
                    break;
                    // 過濾類型爲 REGEX
                case REGEX:
                    typeFilters.add(new RegexPatternTypeFilter(Pattern.compile(expression)));
                    break;
                default:
                    throw new IllegalArgumentException("Filter type not supported with String pattern: " + filterType);
            }
        }

        return typeFilters;
    }
}
3.3.1.1.3.3 doScan
//ClassPathBeanDefinitionScanner#執行包掃描
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    final Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    for (final String basePackage : basePackages) {
        //根據basePackage加載包下全部java文件,並掃描出全部bean組件, 
        //findCandidateComponents方法內部調用
        //ClassPathScanningCandidateComponentProvider.scanCandidateComponents(backPackages)
        final Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        //遍歷beandefition
        for (final BeanDefinition candidate : candidates) {
            //解析做用域Scope
            final ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            final String beanName = beanNameGenerator.generateBeanName(candidate, registry);
            if (candidate instanceof AbstractBeanDefinition) {
                // 應用默認配置
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            //通用註解解析到candidate結構中,主要是處理Lazy, primary DependsOn, Role ,Description這五個註解
            if (candidate instanceof AnnotatedBeanDefinition) {
                // 處理 BeanDefinition 相關注解
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            //檢查當前bean是否已經註冊,不存在則註冊
            if (checkCandidate(beanName, candidate)) {
                // 建立 BeanDefinitionHolder
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                // 嘗試應用代理模式
                definitionHolder =
                        AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, registry);
                // 添加到 beanDefinitions 進行循環處理
                beanDefinitions.add(definitionHolder);
                // 註冊到ioc容器中,主要是一些@Component組件,@Bean註解方法並無在此處註冊,
                // definitionHolder: beanname和beandefinition 鍵值對
                registerBeanDefinition(definitionHolder, registry);
            }
        }
    }
    return beanDefinitions;
}
3.3.1.1.3.4 AnnotationConfigUtils
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
    processCommonDefinitionAnnotations(abd, abd.getMetadata());
}

static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
    // 1)目標元素存在 @Lazy 註解
    AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
    if (lazy != null) {
        abd.setLazyInit(lazy.getBoolean("value"));
    }
    else if (abd.getMetadata() != metadata) {
        lazy = attributesFor(abd.getMetadata(), Lazy.class);
        if (lazy != null) {
            abd.setLazyInit(lazy.getBoolean("value"));
        }
    }

    // 2)目標元素存在 @Primary 註解
    if (metadata.isAnnotated(Primary.class.getName())) {
        abd.setPrimary(true);
    }

    // 3)目標元素存在 @DependsOn 註解
    final AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
    if (dependsOn != null) {
        abd.setDependsOn(dependsOn.getStringArray("value"));
    }

    // 4)目標元素存在 @Role 註解
    final AnnotationAttributes role = attributesFor(metadata, Role.class);
    if (role != null) {
        abd.setRole(role.getNumber("value").intValue());
    }

    // 5)目標元素存在 @Description 註解
    final AnnotationAttributes description = attributesFor(metadata, Description.class);
    if (description != null) {
        abd.setDescription(description.getString("value"));
    }
}

static BeanDefinitionHolder applyScopedProxyMode(
        ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
    // 讀取代理模式
    final ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
    if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
        return definition;
    }
    // 若是是基於 CGLIB 的類代理
    final boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
    return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
3.3.1.1.3.5 ClassPathScanningCandidateComponentProvider
//掃描指定的類路徑
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
    if (componentsIndex != null && indexSupportsIncludeFilters()) {
        return addCandidateComponentsFromIndex(componentsIndex, basePackage);
    }
    else {
        // 掃描組件
        return scanCandidateComponents(basePackage);
    }
}
//實現bean定義信息掃描
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    final Set<BeanDefinition> candidates = new LinkedHashSet<>();
    try {
        // @ComponentScan("com.sl.springlearning.extension")包路徑處理:
        // packageSearchPath = classpath*:com/sl/springlearning/extension/**/*.class
        final String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                resolveBasePackage(basePackage) + '/' + resourcePattern;
        // 經過 ServletContextResourcePatternResolver 讀取全部資源(當前包下全部的class文件)
        final Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
        final boolean traceEnabled = logger.isTraceEnabled();
        final boolean debugEnabled = logger.isDebugEnabled();
        // 循環處理全部資源
        for (final Resource resource : resources) {
            if (traceEnabled) {
                logger.trace("Scanning " + resource);
            }
            // 資源是可讀取的
            if (resource.isReadable()) {
                try {
                    // 讀取 MetadataReader
                    final MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                    //按照scanner過濾器過濾,好比配置類自己將被過濾掉,沒有@Component等組件註解的類將過濾掉
                    if (isCandidateComponent(metadataReader)) {
                        // 基於 MetadataReader 建立 ScannedGenericBeanDefinition
                        final ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                        sbd.setResource(resource);
                        sbd.setSource(resource);
                        // 是不是候選組件
                        if (isCandidateComponent(sbd)) {
                            if (debugEnabled) {
                                logger.debug("Identified candidate component class: " + resource);
                            }
                            candidates.add(sbd);
                        }
                        else {
                            if (debugEnabled) {
                                logger.debug("Ignored because not a concrete top-level class: " + resource);
                            }
                        }
                    }
                    else {
                        if (traceEnabled) {
                            logger.trace("Ignored because not matching any filter: " + resource);
                        }
                    }
                }
                catch (final Throwable ex) {
                    throw new BeanDefinitionStoreException(
                            "Failed to read candidate component class: " + resource, ex);
                }
            }
            else {
                if (traceEnabled) {
                    logger.trace("Ignored because not readable: " + resource);
                }
            }
        }
    }
    catch (final IOException ex) {
        throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
    }
    return candidates;
}

/**
 *  將類名解析爲資源路徑
 *  爲了不多餘的替換操做,能夠直接使用 / 做爲包分隔符
 */
protected String resolveBasePackage(String basePackage) {
    return ClassUtils.convertClassNameToResourcePath(getEnvironment().resolveRequiredPlaceholders(basePackage));
}

/**
 *  目標類不匹配任何排除過濾器,而且至少匹配一個包含過濾器
 */
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
    for (final TypeFilter tf : excludeFilters) {
        // 匹配當期排除過濾器
        if (tf.match(metadataReader, getMetadataReaderFactory())) {
            return false;
        }
    }
    for (final TypeFilter tf : includeFilters) {
        // 匹配當前包含過濾器
        if (tf.match(metadataReader, getMetadataReaderFactory())) {
            return isConditionMatch(metadataReader);
        }
    }
    return false;
}

/**
 *  目標 BeanDefinition 是不是一個候選組件
 */
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
    final AnnotationMetadata metadata = beanDefinition.getMetadata();
    /**
     *  目標類型不是接口,而且不依賴於封閉類【不是內部類】
     */
    return metadata.isIndependent() && (metadata.isConcrete() ||
            metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()));
}
3.3.1.1.3.6 ServletContextResourcePatternResolver
/**
 * 可配置 ServletContext 的 PathMatchingResourcePatternResolver
 */
public class ServletContextResourcePatternResolver extends PathMatchingResourcePatternResolver {
    private static final Log logger = LogFactory.getLog(ServletContextResourcePatternResolver.class);

    public ServletContextResourcePatternResolver(ServletContext servletContext) {
        super(new ServletContextResourceLoader(servletContext));
    }

    public ServletContextResourcePatternResolver(ResourceLoader resourceLoader) {
        super(resourceLoader);
    }

    @Override
    protected Set<Resource> doFindPathMatchingFileResources(Resource rootDirResource, String subPattern)
            throws IOException {
        // 若是跟路徑資源是 ServletContextResource
        if (rootDirResource instanceof ServletContextResource) {
            final ServletContextResource scResource = (ServletContextResource) rootDirResource;
            final ServletContext sc = scResource.getServletContext();
            final String fullPattern = scResource.getPath() + subPattern;
            final Set<Resource> result = new LinkedHashSet<>(8);
            doRetrieveMatchingServletContextResources(sc, fullPattern, scResource.getPath(), result);
            return result;
        }
        else {
            // 默認是 UrlResource
            return super.doFindPathMatchingFileResources(rootDirResource, subPattern);
        }
    }
}
3.3.1.1.3.7 PathMatchingResourcePatternResolver
@Override
public Resource[] getResources(String locationPattern) throws IOException {
    Assert.notNull(locationPattern, "Location pattern must not be null");
    // 資源路徑以 classpath*: 開頭
    if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
        /**
         * 支持多個同名文件
         * a class path resource (multiple resources for same name possible)
         * 資源路徑是 Ant 風格的通配符
         */
        if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
            // a class path resource pattern
            return findPathMatchingResources(locationPattern);
        }
        else {
            // 讀取 classpath 特定根路徑下的全部資源
            return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
        }
    }
    else {
        // Generally only look for a pattern after a prefix here, and on Tomcat only after the "*/" separator for its "war:" protocol.
        final int prefixEnd = locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 :
            locationPattern.indexOf(':') + 1;
        if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
            // a file pattern
            return findPathMatchingResources(locationPattern);
        }
        else {
            // a single resource with the given name
            return new Resource[] {getResourceLoader().getResource(locationPattern)};
        }
    }
}

/**
 *  經過 Ant 風格的路徑匹配器查找全部匹配資源
 */
protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
    // 肯定給定位置的根目錄:classpath*:org/zxd/spring5/
    final String rootDirPath = determineRootDir(locationPattern);
    // 截取模糊匹配路徑:**/*.class
    final String subPattern = locationPattern.substring(rootDirPath.length());
    // 讀取根路徑 Resource
    final Resource[] rootDirResources = getResources(rootDirPath);
    final Set<Resource> result = new LinkedHashSet<>(16);
    // 遍歷全部根路徑
    for (Resource rootDirResource : rootDirResources) {
        rootDirResource = resolveRootDirResource(rootDirResource);
        // 獲取根路徑 URL
        URL rootDirUrl = rootDirResource.getURL();
        // 1)URL 協議以 bundle 開頭
        if (equinoxResolveMethod != null && rootDirUrl.getProtocol().startsWith("bundle")) {
            final URL resolvedUrl = (URL) ReflectionUtils.invokeMethod(equinoxResolveMethod, null, rootDirUrl);
            if (resolvedUrl != null) {
                rootDirUrl = resolvedUrl;
            }
            rootDirResource = new UrlResource(rootDirUrl);
        }
        // 2)URL 協議以 vfs 開頭
        if (rootDirUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
            result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirUrl, subPattern, getPathMatcher()));
        }
        // 3)URL 是一個 jar:jar、war、zip、vfszip、wsjar
        else if (ResourceUtils.isJarURL(rootDirUrl) || isJarResource(rootDirResource)) {
            result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirUrl, subPattern));
        }
        else {
            // 4)URL 協議以 file 開頭
            result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
        }
    }
    if (logger.isTraceEnabled()) {
        logger.trace("Resolved location pattern [" + locationPattern + "] to resources " + result);
    }
    return result.toArray(new Resource[0]);
}

protected Resource[] findAllClassPathResources(String location) throws IOException {
    String path = location;
    if (path.startsWith("/")) {
        path = path.substring(1);
    }
    // 讀取全部的 ClassPathResource
    final Set<Resource> result = doFindAllClassPathResources(path);
    if (logger.isTraceEnabled()) {
        logger.trace("Resolved classpath location [" + location + "] to resources " + result);
    }
    return result.toArray(new Resource[0]);
}

protected Set<Resource> doFindAllClassPathResources(String path) throws IOException {
    final Set<Resource> result = new LinkedHashSet<>(16);
    // 讀取類加載器
    final ClassLoader cl = getClassLoader();
    // 讀取指定包路徑【org/zxd/spring5/】下全部資源的 URL
    final Enumeration<URL> resourceUrls = cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path);
    while (resourceUrls.hasMoreElements()) {
        final URL url = resourceUrls.nextElement();
        result.add(convertClassLoaderURL(url));
    }
    if ("".equals(path)) {
        // The above result is likely to be incomplete, i.e. only containing file system references.
        // We need to have pointers to each of the jar files on the classpath as well...
        addAllClassLoaderJarRoots(cl, result);
    }
    return result;
}

/**
 *  將 URL 轉換爲  UrlResource
 */
protected Resource convertClassLoaderURL(URL url) {
    return new UrlResource(url);
}
3.3.1.1.3.8 ConfigurationClassBeanDefinitionReader

配置類 BeanDefinition 讀取器

/**
 *  從一組完整的 ConfigurationClass 類中解析 BeanDefinition
 *  並將其註冊到 BeanDefinitionRegistry 中。
 */
class ConfigurationClassBeanDefinitionReader {

    private static final Log logger = LogFactory.getLog(ConfigurationClassBeanDefinitionReader.class);

    private static final ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();

    private final BeanDefinitionRegistry registry;

    private final SourceExtractor sourceExtractor;

    private final ResourceLoader resourceLoader;

    private final Environment environment;

    private final BeanNameGenerator importBeanNameGenerator;

    private final ImportRegistry importRegistry;

    private final ConditionEvaluator conditionEvaluator;


    /**
     * Create a new {@link ConfigurationClassBeanDefinitionReader} instance
     * that will be used to populate the given {@link BeanDefinitionRegistry}.
     */
    ConfigurationClassBeanDefinitionReader(BeanDefinitionRegistry registry, SourceExtractor sourceExtractor,
            ResourceLoader resourceLoader, Environment environment, BeanNameGenerator importBeanNameGenerator,
            ImportRegistry importRegistry) {

        registry = registry;
        sourceExtractor = sourceExtractor;
        resourceLoader = resourceLoader;
        environment = environment;
        importBeanNameGenerator = importBeanNameGenerator;
        importRegistry = importRegistry;
        conditionEvaluator = new ConditionEvaluator(registry, environment, resourceLoader);
    }


    /**
     *  從已解析的 ConfigurationClass 中讀取 BeanDefinition
     */
    public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
        TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
        for (ConfigurationClass configClass : configurationModel) {
            loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
        }
    }

    /**
     *  讀取一個特定的 ConfigurationClass 並註冊 BeanDefinition
     */
    private void loadBeanDefinitionsForConfigurationClass(
            ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
        // 是否須要忽略此配置類
        if (trackedConditionEvaluator.shouldSkip(configClass)) {
            String beanName = configClass.getBeanName();
            // 將其從 BeanDefinitionRegistry 中移除
            if (StringUtils.hasLength(beanName) && registry.containsBeanDefinition(beanName)) {
                registry.removeBeanDefinition(beanName);
            }
            // 將此類從 importRegistry 中移除
            importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
            return;
        }

        // 1)此配置類是經過 @Import 導入的
        if (configClass.isImported()) {
            registerBeanDefinitionForImportedConfigurationClass(configClass);
        }

        // 2)處理全部經過 @Bean 註解的方法
        for (BeanMethod beanMethod : configClass.getBeanMethods()) {
            loadBeanDefinitionsForBeanMethod(beanMethod);
        }

        // 解析經過 @ImportResource 導入的配置文件
        loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
        // 解析經過 @Import 導入的 ImportBeanDefinitionRegistrar
        loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
    }

    /**
     *  將配置類自己註冊到 BeanDefinitionRegistry 中
     */
    private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
        AnnotationMetadata metadata = configClass.getMetadata();
        AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);

        ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
        configBeanDef.setScope(scopeMetadata.getScopeName());
        String configBeanName = importBeanNameGenerator.generateBeanName(configBeanDef, registry);
        AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);

        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, registry);
        registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
        configClass.setBeanName(configBeanName);

        if (logger.isTraceEnabled()) {
            logger.trace("Registered bean definition for imported class '" + configBeanName + "'");
        }
    }

    @SuppressWarnings("deprecation")  // for RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE
    private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
        ConfigurationClass configClass = beanMethod.getConfigurationClass();
        MethodMetadata metadata = beanMethod.getMetadata();
        // 讀取方法名稱
        String methodName = metadata.getMethodName();

        // 此 Bean 是否已經被忽略
        if (configClass.skippedBeanMethods.contains(methodName)) {
            return;
        }

        // 此 Bean 是否須要忽略
        if (conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
            configClass.skippedBeanMethods.add(methodName);
            return;
        }

        // 讀取 @Bean 註解的屬性
        AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
        Assert.state(bean != null, "No @Bean annotation attributes");

        // 讀取 bean 名稱
        List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
        // 若是配置了 bean 名稱,則獲取第一個;不然以方法名稱做爲 bean 的名稱
        String beanName = !names.isEmpty() ? names.remove(0) : methodName;

        // 嘗試註冊別名
        for (String alias : names) {
            registry.registerAlias(beanName, alias);
        }

        // Has this effectively been overridden before (e.g. via XML)?
        if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
            if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
                throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
                        beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
                        "' clashes with bean name for containing configuration class; please make those names unique!");
            }
            return;
        }

        // 建立 ConfigurationClassBeanDefinition
        ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
        beanDef.setResource(configClass.getResource());
        beanDef.setSource(sourceExtractor.extractSource(metadata, configClass.getResource()));

        // @Bean 標註的方法是靜態方法
        if (metadata.isStatic()) {
            // static @Bean method
            beanDef.setBeanClassName(configClass.getMetadata().getClassName());
            beanDef.setFactoryMethodName(methodName);
        }
        // @Bean 標註的方法是實例方法
        else {
            // instance @Bean method
            beanDef.setFactoryBeanName(configClass.getBeanName());
            beanDef.setUniqueFactoryMethodName(methodName);
        }
        // 配置屬性
        beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
        beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
                SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);

        // 處理通用 BeanDefinition 註解
        AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);

        // 寫入 Autowire
        Autowire autowire = bean.getEnum("autowire");
        if (autowire.isAutowire()) {
            beanDef.setAutowireMode(autowire.value());
        }

        // 寫入 AutowireCandidate
        boolean autowireCandidate = bean.getBoolean("autowireCandidate");
        if (!autowireCandidate) {
            beanDef.setAutowireCandidate(false);
        }

        // 寫入初始化方法
        String initMethodName = bean.getString("initMethod");
        if (StringUtils.hasText(initMethodName)) {
            beanDef.setInitMethodName(initMethodName);
        }

        // 寫入銷燬方法
        String destroyMethodName = bean.getString("destroyMethod");
        beanDef.setDestroyMethodName(destroyMethodName);

        // Consider scoping
        ScopedProxyMode proxyMode = ScopedProxyMode.NO;
        AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
        if (attributes != null) {
            beanDef.setScope(attributes.getString("value"));
            proxyMode = attributes.getEnum("proxyMode");
            if (proxyMode == ScopedProxyMode.DEFAULT) {
                proxyMode = ScopedProxyMode.NO;
            }
        }

        // Replace the original bean definition with the target one, if necessary
        BeanDefinition beanDefToRegister = beanDef;
        if (proxyMode != ScopedProxyMode.NO) {
            BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
                    new BeanDefinitionHolder(beanDef, beanName), registry,
                    proxyMode == ScopedProxyMode.TARGET_CLASS);
            beanDefToRegister = new ConfigurationClassBeanDefinition(
                    (RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
        }

        if (logger.isTraceEnabled()) {
            logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
                    configClass.getMetadata().getClassName(), beanName));
        }

        // 註冊此 BeanDefinition
        registry.registerBeanDefinition(beanName, beanDefToRegister);
    }

    protected boolean isOverriddenByExistingDefinition(BeanMethod beanMethod, String beanName) {
        if (!registry.containsBeanDefinition(beanName)) {
            return false;
        }
        BeanDefinition existingBeanDef = registry.getBeanDefinition(beanName);

        // Is the existing bean definition one that was created from a configuration class?
        // -> allow the current bean method to override, since both are at second-pass level.
        // However, if the bean method is an overloaded case on the same configuration class,
        // preserve the existing bean definition.
        if (existingBeanDef instanceof ConfigurationClassBeanDefinition) {
            ConfigurationClassBeanDefinition ccbd = (ConfigurationClassBeanDefinition) existingBeanDef;
            return ccbd.getMetadata().getClassName().equals(
                    beanMethod.getConfigurationClass().getMetadata().getClassName());
        }

        // A bean definition resulting from a component scan can be silently overridden
        // by an @Bean method, as of 4.2...
        if (existingBeanDef instanceof ScannedGenericBeanDefinition) {
            return false;
        }

        // Has the existing bean definition bean marked as a framework-generated bean?
        // -> allow the current bean method to override it, since it is application-level
        if (existingBeanDef.getRole() > BeanDefinition.ROLE_APPLICATION) {
            return false;
        }

        // At this point, it's a top-level override (probably XML), just having been parsed
        // before configuration class processing kicks in...
        if (registry instanceof DefaultListableBeanFactory &&
                !((DefaultListableBeanFactory) registry).isAllowBeanDefinitionOverriding()) {
            throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
                    beanName, "@Bean definition illegally overridden by existing bean definition: " + existingBeanDef);
        }
        if (logger.isDebugEnabled()) {
            logger.debug(String.format("Skipping bean definition for %s: a definition for bean '%s' " +
                    "already exists. This top-level bean definition is considered as an override.",
                    beanMethod, beanName));
        }
        return true;
    }

    private void loadBeanDefinitionsFromImportedResources(
            Map<String, Class<? extends BeanDefinitionReader>> importedResources) {
        Map<Class<?>, BeanDefinitionReader> readerInstanceCache = new HashMap<>();
        importedResources.forEach((resource, readerClass) -> {
            // 使用默認的 BeanDefinitionReader
            if (BeanDefinitionReader.class == readerClass) {
                // 目標資源以 .groovy 結尾,則使用 GroovyBeanDefinitionReader 進行讀取
                if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) {
                    // When clearly asking for Groovy, that's what they'll get...
                    readerClass = GroovyBeanDefinitionReader.class;
                }
                else {
                    // 不然使用 XmlBeanDefinitionReader 進行讀取
                    readerClass = XmlBeanDefinitionReader.class;
                }
            }

            // 讀取緩存的 BeanDefinitionReader
            BeanDefinitionReader reader = readerInstanceCache.get(readerClass);
            if (reader == null) {
                try {
                    // 實例化特定的 BeanDefinitionReader
                    reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(registry);
                    // Delegate the current ResourceLoader to it if possible
                    if (reader instanceof AbstractBeanDefinitionReader) {
                        AbstractBeanDefinitionReader abdr = (AbstractBeanDefinitionReader) reader;
                        abdr.setResourceLoader(resourceLoader);
                        abdr.setEnvironment(environment);
                    }
                    readerInstanceCache.put(readerClass, reader);
                }
                catch (Throwable ex) {
                    throw new IllegalStateException(
                            "Could not instantiate BeanDefinitionReader class [" + readerClass.getName() + "]");
                }
            }

            // 使用 BeanDefinitionReader 讀取 BeanDefinition
            // TODO SPR-6310: qualify relative path locations as done in AbstractContextLoader.modifyLocations
            reader.loadBeanDefinitions(resource);
        });
    }

    /**
     *  經過 ImportBeanDefinitionRegistrar 註冊 BeanDefinition
     */
    private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
        registrars.forEach((registrar, metadata) ->
        registrar.registerBeanDefinitions(metadata, registry));
    }

    @SuppressWarnings("serial")
    private static class ConfigurationClassBeanDefinition extends RootBeanDefinition implements AnnotatedBeanDefinition {
        /**
         *  註解元數據
         */
        private final AnnotationMetadata annotationMetadata;
        /**
         *  方法元數據
         */
        private final MethodMetadata factoryMethodMetadata;

        public ConfigurationClassBeanDefinition(ConfigurationClass configClass, MethodMetadata beanMethodMetadata) {
            annotationMetadata = configClass.getMetadata();
            factoryMethodMetadata = beanMethodMetadata;
            setLenientConstructorResolution(false);
        }

        public ConfigurationClassBeanDefinition(
                RootBeanDefinition original, ConfigurationClass configClass, MethodMetadata beanMethodMetadata) {
            super(original);
            annotationMetadata = configClass.getMetadata();
            factoryMethodMetadata = beanMethodMetadata;
        }

        private ConfigurationClassBeanDefinition(ConfigurationClassBeanDefinition original) {
            super(original);
            annotationMetadata = original.annotationMetadata;
            factoryMethodMetadata = original.factoryMethodMetadata;
        }

        @Override
        public AnnotationMetadata getMetadata() {
            return annotationMetadata;
        }

        @Override
        public MethodMetadata getFactoryMethodMetadata() {
            return factoryMethodMetadata;
        }

        @Override
        public boolean isFactoryMethod(Method candidate) {
            return super.isFactoryMethod(candidate) && BeanAnnotationHelper.isBeanAnnotated(candidate);
        }

        @Override
        public ConfigurationClassBeanDefinition cloneBeanDefinition() {
            return new ConfigurationClassBeanDefinition(this);
        }
    }

    private class TrackedConditionEvaluator {
        private final Map<ConfigurationClass, Boolean> skipped = new HashMap<>();

        public boolean shouldSkip(ConfigurationClass configClass) {
            Boolean skip = skipped.get(configClass);
            if (skip == null) {
                if (configClass.isImported()) {
                    boolean allSkipped = true;
                    for (ConfigurationClass importedBy : configClass.getImportedBy()) {
                        if (!shouldSkip(importedBy)) {
                            allSkipped = false;
                            break;
                        }
                    }
                    if (allSkipped) {
                        // The config classes that imported this one were all skipped, therefore we are skipped...
                        skip = true;
                    }
                }
                if (skip == null) {
                    skip = conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN);
                }
                skipped.put(configClass, skip);
            }
            return skip;
        }
    }
}
3.3.1.1.4 處理全部的 @Import 註解
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
            Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
        // 若是配置類上沒有任何候選@Import(importCandidates),
        //說明沒有須要處理的導入,則什麼都不用作,直接返回
        if (importCandidates.isEmpty()) {
            return;
        }
        // 進行循環依賴的檢查
        if (checkForCircularImports && isChainedImportOnStack(configClass)) {
            // 若是要求作循環導入檢查,而且檢查到了循環依賴,報告這個問題
            this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
        }
        else {
         // 開始處理配置類configClass上全部的@Import importCandidates
            this.importStack.push(configClass);
            try {
               // 循環處理每個@Import,每一個@Import可能導入三種類型的類 :
                // 1. ImportSelector
                // 2. ImportBeanDefinitionRegistrar
                // 3. 其餘類型,都看成配置類處理,也就是至關於使用了註解@Configuration的配置類
                // 下面的for循環中對這三種狀況執行了不一樣的處理邏輯
                for (SourceClass candidate : importCandidates) {
                      // 目標類是 ImportSelector 實例
                    if (candidate.isAssignable(ImportSelector.class)) {
                        Class<?> candidateClass = candidate.loadClass();
                         // 建立目標實例
                        ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
                        // 執行 BeanClassLoaderAware、BeanFactoryAware、EnvironmentAware、ResourceLoaderAware 注入
                        ParserStrategyUtils.invokeAwareMethods(
                                selector, this.environment, this.resourceLoader, this.registry);
                           // 若是這個類也是DeferredImportSelector接口的實現類,
                    // 那麼加入ConfigurationClassParser的deferredImportSelectors 
                        if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
                            this.deferredImportSelectors.add(
                                    new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
                        }
                        else {//若是不是,則調用processImports 進行處理.
                         // 獲取全部配置類名稱
                            String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                           // 獲取全部配置類名稱
                          Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
                            // 遞歸處理全部導入的配置類
                          processImports(configClass, currentSourceClass, importSourceClasses, false);
                        }
                    }
                     // 若是這個類是ImportBeanDefinitionRegistrar接口的實現類
                // 設置到配置類的importBeanDefinitionRegistrars屬性中
                    else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
        
                        Class<?> candidateClass = candidate.loadClass();
                       // 實例化 ImportBeanDefinitionRegistrar
                        ImportBeanDefinitionRegistrar registrar =
                                BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
                          // 執行 Aware 注入
                        ParserStrategyUtils.invokeAwareMethods(
                                registrar, this.environment, this.resourceLoader, this.registry);
                          // 寫入 importBeanDefinitionRegistrars 緩存
                        configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                    }
                    else {
                        //配置類不是 ImportSelector or ImportBeanDefinitionRegistrar,
                      //則加入到importStack後調用processConfigurationClass 進行處理.
                        // 其它狀況下把這個類入隊到ConfigurationClassParser的importStack(隊列)屬性中
                    // 而後把這個類當成是@Configuration註解修飾的類遞歸重頭開始解析這個類
                        this.importStack.registerImport(
                                currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                        processConfigurationClass(candidate.asConfigClass(configClass));
                    }
                }
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                        "Failed to process import candidates for configuration class [" +
                        configClass.getMetadata().getClassName() + "]", ex);
            }
            finally {
                this.importStack.pop();
            }
        }
    }
3.3.1.1.5 processInterfaces
/**
     *  解析接口上的方法,若是此方法存在 @Bean 註解
     */
    private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
        for (final SourceClass ifc : sourceClass.getInterfaces()) {
            final Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
            for (final MethodMetadata methodMetadata : beanMethods) {
                if (!methodMetadata.isAbstract()) {
                    // A default method or other concrete method on a Java 8+ interface...
                    configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
                }
            }
            processInterfaces(configClass, ifc);
        }
    }

3.3.1.2 ConditionEvaluator條件評估

用於計算 @Conditional 註解的內部類

class ConditionEvaluator {
    private final ConditionContextImpl context;

    public ConditionEvaluator(@Nullable BeanDefinitionRegistry registry,
            @Nullable Environment environment, @Nullable ResourceLoader resourceLoader) {
        context = new ConditionContextImpl(registry, environment, resourceLoader);
    }

    /**
     *  指定類或方法上是否存在 @Conditional 註解,並須要跳過處理流程
     */
    public boolean shouldSkip(AnnotatedTypeMetadata metadata) {
        return shouldSkip(metadata, null);
    }

    public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
        // 註解元數據爲空 || 目標元素不存在 @Conditional 註解,不跳過
        if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
            return false;
        }

        if (phase == null) {
            if (metadata instanceof AnnotationMetadata &&
                    ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
                return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
            }
            return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
        }

        final List<Condition> conditions = new ArrayList<>();
        // 讀取全部的條件類
        for (final String[] conditionClasses : getConditionClasses(metadata)) {
            for (final String conditionClass : conditionClasses) {
                final Condition condition = getCondition(conditionClass, context.getClassLoader());
                conditions.add(condition);
            }
        }
        // 根據 Order 進行排序
        AnnotationAwareOrderComparator.sort(conditions);

        for (final Condition condition : conditions) {
            ConfigurationPhase requiredPhase = null;
            if (condition instanceof ConfigurationCondition) {
                requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
            }
            // 請求階段爲空或請求階段==此階段 && 此條件不匹配
            if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(context, metadata)) {
                return true;
            }
        }

        // 全部的條件都匹配
        return false;
    }

    @SuppressWarnings("unchecked")
    private List<String[]> getConditionClasses(AnnotatedTypeMetadata metadata) {
        // 讀取全部 @Conditional 註解的屬性配置
        final MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(Conditional.class.getName(), true);
        // 讀取評估條件
        final Object values = attributes != null ? attributes.get("value") : null;
        return (List<String[]>) (values != null ? values : Collections.emptyList());
    }

    /**
     *  實例化目標條件
     */
    private Condition getCondition(String conditionClassName, @Nullable ClassLoader classloader) {
        final Class<?> conditionClass = ClassUtils.resolveClassName(conditionClassName, classloader);
        return (Condition) BeanUtils.instantiateClass(conditionClass);
    }

    private static class ConditionContextImpl implements ConditionContext {
        @Nullable
        private final BeanDefinitionRegistry registry;

        @Nullable
        private final ConfigurableListableBeanFactory beanFactory;

        private final Environment environment;

        private final ResourceLoader resourceLoader;

        @Nullable
        private final ClassLoader classLoader;

        public ConditionContextImpl(@Nullable BeanDefinitionRegistry registry,
                @Nullable Environment environment, @Nullable ResourceLoader resourceLoader) {

            this.registry = registry;
            beanFactory = deduceBeanFactory(registry);
            this.environment = environment != null ? environment : deduceEnvironment(registry);
            this.resourceLoader = resourceLoader != null ? resourceLoader : deduceResourceLoader(registry);
            classLoader = deduceClassLoader(resourceLoader, beanFactory);
        }

        @Nullable
        private ConfigurableListableBeanFactory deduceBeanFactory(@Nullable BeanDefinitionRegistry source) {
            if (source instanceof ConfigurableListableBeanFactory) {
                return (ConfigurableListableBeanFactory) source;
            }
            if (source instanceof ConfigurableApplicationContext) {
                return ((ConfigurableApplicationContext) source).getBeanFactory();
            }
            return null;
        }

        /**
         *  推斷 Environment
         */
        private Environment deduceEnvironment(@Nullable BeanDefinitionRegistry source) {
            if (source instanceof EnvironmentCapable) {
                return ((EnvironmentCapable) source).getEnvironment();
            }
            return new StandardEnvironment();
        }

        /**
         *  推斷 ResourceLoader
         */
        private ResourceLoader deduceResourceLoader(@Nullable BeanDefinitionRegistry source) {
            if (source instanceof ResourceLoader) {
                return (ResourceLoader) source;
            }
            return new DefaultResourceLoader();
        }

        /**
         *  推斷 ClassLoader
         */
        @Nullable
        private ClassLoader deduceClassLoader(@Nullable ResourceLoader resourceLoader,
                @Nullable ConfigurableListableBeanFactory beanFactory) {
            if (resourceLoader != null) {
                final ClassLoader classLoader = resourceLoader.getClassLoader();
                if (classLoader != null) {
                    return classLoader;
                }
            }
            if (beanFactory != null) {
                return beanFactory.getBeanClassLoader();
            }
            return ClassUtils.getDefaultClassLoader();
        }

        @Override
        public BeanDefinitionRegistry getRegistry() {
            Assert.state(registry != null, "No BeanDefinitionRegistry available");
            return registry;
        }

        @Override
        @Nullable
        public ConfigurableListableBeanFactory getBeanFactory() {
            return beanFactory;
        }

        @Override
        public Environment getEnvironment() {
            return environment;
        }

        @Override
        public ResourceLoader getResourceLoader() {
            return resourceLoader;
        }

        @Override
        @Nullable
        public ClassLoader getClassLoader() {
            return classLoader;
        }
    }
}

3.3.1.3 ConfigurationClass配置類

ConfigurationClass表明一個配置類,它內部維護了一些已經解析好的可是尚未被加入進Bean定義信息的原始信息,有必要作以下解釋:

//它是普通的類,基本只有get set方法
final class ConfigurationClass {

    private final AnnotationMetadata metadata;

    private final Resource resource;

    @Nullable
    private String beanName;
    
    private final Set<ConfigurationClass> importedBy = new LinkedHashSet<>(1);
    // 存儲該配置類裏全部標註@Bean註解的方法~~~~
    private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();
    // 用Map保存着@ImportResource 導入進來的資源們~
    private final Map<String, Class<? extends BeanDefinitionReader>> importedResources =
            new LinkedHashMap<>();
    // 用Map保存着@Import中實現了`ImportBeanDefinitionRegistrar`接口的內容~
    private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars =
            new LinkedHashMap<>();

    final Set<String> skippedBeanMethods = new HashSet<>();
}

3.3.1.4 ConditionalOnProperty

/**
 *  此 Environment 中是否存在指定的屬性 && 屬性具備存在特定值【若是指定】。
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class) // 經過 @Conditional 註解關聯條件類
public @interface ConditionalOnProperty {
    /**
     *  屬性的名稱
     */
    String[] value() default {};

    /**
     *  每一個屬性的前綴
     */
    String prefix() default "";

    /**
     *  屬性的名稱
     */
    String[] name() default {};

    /**
     *  屬性值
     */
    String havingValue() default "";

    /**
     *  若是 Environment 中不存在此屬性,是否匹配【默認不匹配】
     */
    boolean matchIfMissing() default false;
}

/**
 * 組件被註冊到 BeanDefinitionRegistry 時必須知足的條件
 */
@FunctionalInterface
public interface Condition {

    /**
     *  判斷此條件是否知足
     */
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

public abstract class SpringBootCondition implements Condition {
    private final Log logger = LogFactory.getLog(getClass());

    @Override
    public final boolean matches(ConditionContext context,
            AnnotatedTypeMetadata metadata) {
        // 讀取類名或方法名稱
        String classOrMethodName = getClassOrMethodName(metadata);
        try {
            // 讀取條件的輸出結果
            ConditionOutcome outcome = getMatchOutcome(context, metadata);
            // 記錄日誌
            logOutcome(classOrMethodName, outcome);
            // 記錄評估結果
            recordEvaluation(context, classOrMethodName, outcome);
            // 此條件是否知足
            return outcome.isMatch();
        }
        catch (NoClassDefFoundError ex) {
            throw new IllegalStateException(
                    "Could not evaluate condition on " + classOrMethodName + " due to "
                            + ex.getMessage() + " not "
                            + "found. Make sure your own configuration does not rely on "
                            + "that class. This can also happen if you are "
                            + "@ComponentScanning a springframework package (e.g. if you "
                            + "put a @ComponentScan in the default package by mistake)",
                    ex);
        }
        catch (RuntimeException ex) {
            throw new IllegalStateException(
                    "Error processing condition on " + getName(metadata), ex);
        }
    }

    private String getName(AnnotatedTypeMetadata metadata) {
        if (metadata instanceof AnnotationMetadata) {
            return ((AnnotationMetadata) metadata).getClassName();
        }
        if (metadata instanceof MethodMetadata) {
            MethodMetadata methodMetadata = (MethodMetadata) metadata;
            return methodMetadata.getDeclaringClassName() + "."
                    + methodMetadata.getMethodName();
        }
        return metadata.toString();
    }

    private static String getClassOrMethodName(AnnotatedTypeMetadata metadata) {
        if (metadata instanceof ClassMetadata) {
            ClassMetadata classMetadata = (ClassMetadata) metadata;
            return classMetadata.getClassName();
        }
        MethodMetadata methodMetadata = (MethodMetadata) metadata;
        return methodMetadata.getDeclaringClassName() + "#"
                + methodMetadata.getMethodName();
    }

    protected final void logOutcome(String classOrMethodName, ConditionOutcome outcome) {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace(getLogMessage(classOrMethodName, outcome));
        }
    }

    private StringBuilder getLogMessage(String classOrMethodName,
            ConditionOutcome outcome) {
        StringBuilder message = new StringBuilder();
        message.append("Condition ");
        message.append(ClassUtils.getShortName(getClass()));
        message.append(" on ");
        message.append(classOrMethodName);
        message.append(outcome.isMatch() ? " matched" : " did not match");
        if (StringUtils.hasLength(outcome.getMessage())) {
            message.append(" due to ");
            message.append(outcome.getMessage());
        }
        return message;
    }

    private void recordEvaluation(ConditionContext context, String classOrMethodName,
            ConditionOutcome outcome) {
        if (context.getBeanFactory() != null) {
            ConditionEvaluationReport.get(context.getBeanFactory())
                    .recordConditionEvaluation(classOrMethodName, this, outcome);
        }
    }

    /**
     *  肯定匹配結果
     */
    public abstract ConditionOutcome getMatchOutcome(ConditionContext context,
            AnnotatedTypeMetadata metadata);

    /**
     *  只要有一個條件知足
     */
    protected final boolean anyMatches(ConditionContext context,
            AnnotatedTypeMetadata metadata, Condition... conditions) {
        for (Condition condition : conditions) {
            if (matches(context, metadata, condition)) {
                return true;
            }
        }
        return false;
    }

    /**
     *  指定的條件是否知足
     */
    protected final boolean matches(ConditionContext context,
            AnnotatedTypeMetadata metadata, Condition condition) {
        if (condition instanceof SpringBootCondition) {
            return ((SpringBootCondition) condition).getMatchOutcome(context, metadata)
                    .isMatch();
        }
        return condition.matches(context, metadata);
    }
}

/**
 *  指定的屬性是否認義在此 Environment 中
 */
@Order(Ordered.HIGHEST_PRECEDENCE + 40)
class OnPropertyCondition extends SpringBootCondition {

    @Override
    public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 讀取目標元素上全部的 @ConditionalOnProperty 註解的屬性信息
        final List<AnnotationAttributes> allAnnotationAttributes = annotationAttributesFromMultiValueMap(
                metadata.getAllAnnotationAttributes(ConditionalOnProperty.class.getName()));
        final List<ConditionMessage> noMatch = new ArrayList<>();
        final List<ConditionMessage> match = new ArrayList<>();
        for (final AnnotationAttributes annotationAttributes : allAnnotationAttributes) {
            // 肯定當前 ConditionalOnProperty 條件的輸出結果
            final ConditionOutcome outcome = determineOutcome(annotationAttributes, context.getEnvironment());
            // 記錄 ConditionMessage
            (outcome.isMatch() ? match : noMatch).add(outcome.getConditionMessage());
        }
        // 存在一個不匹配條件
        if (!noMatch.isEmpty()) {
            return ConditionOutcome.noMatch(ConditionMessage.of(noMatch));
        }
        // 全部的條件都匹配
        return ConditionOutcome.match(ConditionMessage.of(match));
    }

    private List<AnnotationAttributes> annotationAttributesFromMultiValueMap(
            MultiValueMap<String, Object> multiValueMap) {
        final List<Map<String, Object>> maps = new ArrayList<>();
        multiValueMap.forEach((key, value) -> {
            for (int i = 0; i < value.size(); i++) {
                Map<String, Object> map;
                if (i < maps.size()) {
                    map = maps.get(i);
                } else {
                    map = new HashMap<>();
                    maps.add(map);
                }
                map.put(key, value.get(i));
            }
        });
        final List<AnnotationAttributes> annotationAttributes = new ArrayList<>(maps.size());
        for (final Map<String, Object> map : maps) {
            annotationAttributes.add(AnnotationAttributes.fromMap(map));
        }
        return annotationAttributes;
    }

    private ConditionOutcome determineOutcome(AnnotationAttributes annotationAttributes, PropertyResolver resolver) {
        final Spec spec = new Spec(annotationAttributes);
        final List<String> missingProperties = new ArrayList<>();
        final List<String> nonMatchingProperties = new ArrayList<>();
        spec.collectProperties(resolver, missingProperties, nonMatchingProperties);
        // 1)屬性值不存在
        if (!missingProperties.isEmpty()) {
            return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnProperty.class, spec)
                    .didNotFind("property", "properties").items(Style.QUOTE, missingProperties));
        }
        // 2)屬性值存在,可是不匹配
        if (!nonMatchingProperties.isEmpty()) {
            return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnProperty.class, spec)
                    .found("different value in property", "different value in properties")
                    .items(Style.QUOTE, nonMatchingProperties));
        }
        // 此 ConditionalOnProperty 條件匹配
        return ConditionOutcome
                .match(ConditionMessage.forCondition(ConditionalOnProperty.class, spec).because("matched"));
    }

    private static class Spec {
        private final String prefix;
        private final String havingValue;
        private final String[] names;
        private final boolean matchIfMissing;

        Spec(AnnotationAttributes annotationAttributes) {
            // 讀取 ConditionalOnProperty 註解的 prefix 屬性
            String prefix = annotationAttributes.getString("prefix").trim();
            // prefix 不爲空,則嘗試添加 . 後綴
            if (StringUtils.hasText(prefix) && !prefix.endsWith(".")) {
                prefix = prefix + ".";
            }
            this.prefix = prefix;
            // 讀取  ConditionalOnProperty 註解的 havingValue 屬性
            havingValue = annotationAttributes.getString("havingValue");
            // 讀取  ConditionalOnProperty 註解的關聯屬性名稱
            names = getNames(annotationAttributes);
            // 讀取 ConditionalOnProperty 註解的 matchIfMissing 屬性
            matchIfMissing = annotationAttributes.getBoolean("matchIfMissing");
        }

        private String[] getNames(Map<String, Object> annotationAttributes) {
            final String[] value = (String[]) annotationAttributes.get("value");
            final String[] name = (String[]) annotationAttributes.get("name");
            Assert.state(value.length > 0 || name.length > 0,
                    "The name or value attribute of @ConditionalOnProperty must be specified");
            Assert.state(value.length == 0 || name.length == 0,
                    "The name and value attributes of @ConditionalOnProperty are exclusive");
            // value 屬性的優先級高於 name
            return value.length > 0 ? value : name;
        }

        private void collectProperties(PropertyResolver resolver, List<String> missing, List<String> nonMatching) {
            // 遍歷全部的屬性名稱
            for (final String name : names) {
                // 添加前綴
                final String key = prefix + name;
                // 1)若是 Environment 中存在此屬性
                if (resolver.containsProperty(key)) {
                    // 指定的值不匹配,則寫入 nonMatching 中
                    if (!isMatch(resolver.getProperty(key), havingValue)) {
                        nonMatching.add(name);
                    }
                    // 2)Environment 中不存在此屬性
                } else {
                    // 若是不能忽略此屬性,則寫入 missing 中
                    if (!matchIfMissing) {
                        missing.add(name);
                    }
                }
            }
        }

        private boolean isMatch(String value, String requiredValue) {
            // 1)指定了必須的值,則使用 equals 進行比較
            if (StringUtils.hasLength(requiredValue)) {
                return requiredValue.equalsIgnoreCase(value);
            }
            // 只要屬性值不是忽略大小寫的 false,就匹配
            return !"false".equalsIgnoreCase(value);
        }

        @Override
        public String toString() {
            final StringBuilder result = new StringBuilder();
            result.append("(");
            result.append(prefix);
            if (names.length == 1) {
                result.append(names[0]);
            } else {
                result.append("[");
                result.append(StringUtils.arrayToCommaDelimitedString(names));
                result.append("]");
            }
            if (StringUtils.hasLength(havingValue)) {
                result.append("=").append(havingValue);
            }
            result.append(")");
            return result.toString();
        }
    }
}

3.4 loadBeanDefinitions加載bean定義信息

ConfigurationClassBeanDefinitionReader.loadBeanDefinitions()方法的功能就是將以前解析出的configClasses配置類信息中全部配置相關的信息添加到spring的bean定義,主要是配置類中的@Bean註解方法,配置類@ImportResource和@Import(實現ImportBeanDefinitionRegistrar接口方式)的bean註冊

ConfigurationClassBeanDefinitionReader.loadBeanDefinitions()方法 實現邏輯以下:

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
   TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
   for (ConfigurationClass configClass : configurationModel) {
      loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
   }
}
private void loadBeanDefinitionsForConfigurationClass(
      ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
     if (trackedConditionEvaluator.shouldSkip(configClass)) {
      String beanName = configClass.getBeanName();
      if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
         this.registry.removeBeanDefinition(beanName);
      }
      this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
      return;
   }

   if (configClass.isImported()) {
      registerBeanDefinitionForImportedConfigurationClass(configClass);
   }
  //將@Bean方法註冊爲bean
   for (BeanMethod beanMethod : configClass.getBeanMethods()) {
      loadBeanDefinitionsForBeanMethod(beanMethod);
   }
   //將configClass中中ImportResource指定的資源註冊爲bean
   loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
//將configClass中ImportedRegistrar註冊爲bean
   loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

處理邏輯理了一遍後,看一下ConfigurationClassPostProcessor處理器解析@configuration配置類主要過程:

  1. Spring容器初始化時註冊默認後置處理器ConfigurationClassPostProcessor

  2. Spring容器初始化執行refresh()方法中調用ConfigurationClassPostProcessor

  3. ConfigurationClassPostProcessor處理器藉助ConfigurationClassParser完成配置類解析

  4. ConfigurationClassParser配置內解析過程當中完成嵌套的MemberClass、@PropertySource註解、@ComponentScan註解(掃描package下的全部Class並進行迭代解析,主要是@Component組件解析及註冊)、@ImportResource、@Bean等處理

  5. 完成@Bean註冊, @ImportResource指定bean的註冊以及@Import(實現ImportBeanDefinitionRegistrar接口方式)的bean註冊

4 總結

掃描Bean的順序(並非Bean定義真正註冊的順序):

  1. 內部配置類:–> 它裏面還能夠有普通配置類如出一轍的功能,但優先級最高,最終會放在configurationClasses這個Map的第一位
  2. @PropertySource:這個和Bean定義沒啥關係,屬於Spring配置PropertySource的範疇。這個屬性優先級相對較低
  3. @ComponentScan:這裏掃描到的Bean定義,就直接register註冊了。因此它的時機是很是早的。(另外:若是註冊進去的Bean定義信息仍是配置類,這裏會繼續parse(),因此最終能被掃描到的組件,最終都會看成一個配置類來處理,因此最終都會放進configurationClasses這個Map裏面去)
  4. @Import:相對複雜點,以下:

    1. 如果一個普通類(標註@Configuration與否都無所謂反正會看成一個配置類來處理,也會放進configurationClasses緩存進去)
    2. 實現了ImportSelector:遞歸最後都成爲第一步的類。若實現的是DeferredImportSelector接口,它會放在deferredImportSelectors屬性裏先保存着,等着外部全部的configCandidates配置類所有解析完成後,統一processDeferredImportSelectors(),最終也是轉爲第一步的類。
    3. 實現了ImportBeanDefinitionRegistrar:放在ConfigurationClass.importBeanDefinitionRegistrars屬性裏保存着
  5. @ImportResource:通常用來導入xml文件。它是先放在ConfigurationClass.importedResources屬性裏放着
  6. @Bean:找到全部@Bean的方法,而後保存到ConfigurationClass.beanMethods屬性裏
  7. processInterfaces:處理該類實現的接口們的default方法(標註@Bean的有效)
  8. 處理父類:拿到父類,每一個父類都是看成一個配置文件來處理。備註:!superclass.startsWith("java")全類名不以java打頭,且沒有被處理過(由於一個父類能夠有N個子類,但只能被處理一次)
  9. return null:若所有處理完成後就返回null,中止遞歸。

由上可見,這九步中,惟獨只有@ComponentScan掃描到的Bean這個時候的Bean定義信息是已經註冊上去了的,其他的都尚未真正註冊到註冊中心。

注意:bean註冊的前後順序,將直接影響到Bean的覆蓋(默認Map,後註冊的覆蓋先註冊的,固然還和scope有關)

相關文章
相關標籤/搜索