劍指Spring源碼(二)

這是春節(jié)后的第一篇博客彪见,我在構(gòu)思這篇博客的時(shí)候儡司,一度想放棄,想想要不要換個(gè)東西寫余指,因?yàn)楫吘箓€(gè)人水平有限捕犬,Spring源碼實(shí)在博大精深,不是我這個(gè)菜的摳腳的菜雞可以駕馭的,怕誤人子弟碉碉,還有就是源碼分析類的博客實(shí)在是太難寫了柴钻,和一般的博客真心不同,可能寫了很多垢粮,自己都不知道自己在寫些什么贴届,但是還是要堅(jiān)持,從接觸博客的那一天開始足丢,就非常佩服那些大神粱腻,樂于分享,無(wú)私奉獻(xiàn)斩跌,我也從那些博客中學(xué)到了不少東西绍些,慢慢的從一個(gè)嫩嫩的小菜雞變成了禿頭大菜雞,其中最佩服的就是那些源碼分析類的博客耀鸦,雖然看不懂柬批,但是從博客中,我分明讀出了大神們對(duì)技術(shù)的熱愛袖订,對(duì)技術(shù)的堅(jiān)持介杆,對(duì)技術(shù)的執(zhí)著膀值。堅(jiān)持!

在上一篇Spring源碼解析中,我們分析了

    //根據(jù)參數(shù)類型可以知道燃观,其實(shí)可以傳入多個(gè)annotatedClasses,但是這種情況出現(xiàn)的比較少
    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        //調(diào)用無(wú)參構(gòu)造函數(shù)逢防,會(huì)先調(diào)用父類GenericApplicationContext的構(gòu)造函數(shù)
        //父類的構(gòu)造函數(shù)里面就是初始化DefaultListableBeanFactory犀农,并且賦值給beanFactory
        //本類的構(gòu)造函數(shù)里面,初始化了一個(gè)讀取器:AnnotatedBeanDefinitionReader read硫眯,一個(gè)掃描器ClassPathBeanDefinitionScanner scanner
        //scanner的用處不是很大蕴侧,它僅僅是在我們外部手動(dòng)調(diào)用 .scan 等方法才有用,常規(guī)方式是不會(huì)用到scanner對(duì)象的
        this();
        //把傳入的類進(jìn)行注冊(cè)两入,這里有兩個(gè)情況净宵,
        //傳入傳統(tǒng)的配置類
        //傳入bean(雖然一般沒有人會(huì)這么做
        //看到后面會(huì)知道spring把傳統(tǒng)的帶上@Configuration的配置類稱之為FULL配置類,不帶@Configuration的稱之為L(zhǎng)ite配置類
        //但是我們這里先把帶上@Configuration的配置類稱之為傳統(tǒng)配置類裹纳,不帶的稱之為普通bean
        register(annotatedClasses);
        //刷新
        refresh();
    }

中的前兩行代碼择葡,回顧下,這兩行代碼痊夭,主要是把我們的配置類和內(nèi)置的幾個(gè)后置處理器放到了兩個(gè)集合中:

                //beanDefinitionMap是Map<String, BeanDefinition>刁岸,
                //這里就是把beanName作為key,beanDefinition作為value她我,推到map里面
                this.beanDefinitionMap.put(beanName, beanDefinition);

                //beanDefinitionNames就是一個(gè)List<String>,這里就是把beanName放到List中去
                this.beanDefinitionNames.add(beanName);

今天虹曙,我們來分析下第三行代碼迫横,即:

        //刷新
        refresh();

這個(gè)方法做了很多事情,讓我們點(diǎn)開這個(gè)方法:

    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            //刷新預(yù)處理酝碳,和主流程關(guān)系不大矾踱,就是保存了容器的啟動(dòng)時(shí)間,啟動(dòng)標(biāo)志等
            prepareRefresh();

            //DefaultListableBeanFactory
            // Tell the subclass to refresh the internal bean factory.
            //和主流程關(guān)系也不大疏哗,最終獲得了DefaultListableBeanFactory呛讲,
            // DefaultListableBeanFactory實(shí)現(xiàn)了ConfigurableListableBeanFactory
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            //還是一些準(zhǔn)備工作,添加了兩個(gè)后置處理器:ApplicationContextAwareProcessor返奉,ApplicationListenerDetector
            //還設(shè)置了 忽略自動(dòng)裝配 和 允許自動(dòng)裝配 的接口,如果不存在某個(gè)bean的時(shí)候贝搁,spring就自動(dòng)注冊(cè)singleton bean
            //還設(shè)置了bean表達(dá)式解析器 等
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                //這是一個(gè)空方法
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                //執(zhí)行自定義的BeanFactoryProcessor和內(nèi)置的BeanFactoryProcessor
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                // 注冊(cè)BeanPostProcessor
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                // 空方法
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

里面有很多小方法,我們今天的目標(biāo)是分析前五個(gè)小方法:

prepareRefresh

從命名來看芽偏,就知道這個(gè)方法主要做了一些刷新前的準(zhǔn)備工作雷逆,和主流程關(guān)系不大,主要是保存了容器的啟動(dòng)時(shí)間污尉,啟動(dòng)標(biāo)志等膀哲。

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()

這個(gè)方法和主流程關(guān)系也不是很大,可以簡(jiǎn)單的認(rèn)為被碗,就是把beanFactory取出來而已某宪。

prepareBeanFactory

            //還是一些準(zhǔn)備工作,添加了兩個(gè)后置處理器:ApplicationContextAwareProcessor锐朴,ApplicationListenerDetector
            //還設(shè)置了 忽略自動(dòng)裝配 和 允許自動(dòng)裝配 的接口,如果不存在某個(gè)bean的時(shí)候兴喂,spring就自動(dòng)注冊(cè)singleton bean
            //還設(shè)置了bean表達(dá)式解析器 等
            prepareBeanFactory(beanFactory);

這代碼相比前面兩個(gè)就比較重要了,我們需要點(diǎn)進(jìn)去好好看看焚志,做了什么操作:

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        beanFactory.setBeanClassLoader(getClassLoader());//設(shè)置類加載器

        //設(shè)置bean表達(dá)式解析器
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

        //屬性編輯器支持
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // Configure the bean factory with context callbacks.
        //添加一個(gè)后置處理器:ApplicationContextAwareProcessor瞻想,此后置處理處理器實(shí)現(xiàn)了BeanPostProcessor接口
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

        //以下接口,忽略自動(dòng)裝配
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

        // BeanFactory interface not registered as resolvable type in a plain factory.
        // MessageSource registered (and found for autowiring) as a bean.
        //以下接口娩嚼,允許自動(dòng)裝配,第一個(gè)參數(shù)是自動(dòng)裝配的類型,滴肿,第二個(gè)字段是自動(dòng)裝配的值
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        // Register early post-processor for detecting inner beans as ApplicationListeners.
        //添加一個(gè)后置處理器:ApplicationListenerDetector岳悟,此后置處理器實(shí)現(xiàn)了BeanPostProcessor接口
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        //如果沒有注冊(cè)過bean名稱為XXX,spring就自己創(chuàng)建一個(gè)名稱為XXX的singleton bean
        //Register default environment beans.

        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
        }
    }

主要做了如下的操作:

  1. 設(shè)置了一個(gè)類加載器
  2. 設(shè)置了bean表達(dá)式解析器
  3. 添加了屬性編輯器的支持
  4. 添加了一個(gè)后置處理器:ApplicationContextAwareProcessor泼差,此后置處理器實(shí)現(xiàn)了BeanPostProcessor接口
  5. 設(shè)置了一些忽略自動(dòng)裝配的接口
  6. 設(shè)置了一些允許自動(dòng)裝配的接口贵少,并且進(jìn)行了賦值操作
  7. 在容器中還沒有XX的bean的時(shí)候,幫我們注冊(cè)beanName為XX的singleton bean

postProcessBeanFactory(beanFactory)

                //這是一個(gè)空方法
                postProcessBeanFactory(beanFactory);

這是一個(gè)空方法堆缘,可能以后Spring會(huì)進(jìn)行擴(kuò)展把滔灶。

invokeBeanFactoryPostProcessors(beanFactory)

                //執(zhí)行自定義的BeanFactoryProcessor和內(nèi)置的BeanFactoryProcessor
                invokeBeanFactoryPostProcessors(beanFactory);

重點(diǎn)代碼終于來了,可以說 這句代碼是目前為止最重要吼肥,也是內(nèi)容最多的代碼了录平,我們有必要好好分析下:

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {

        //getBeanFactoryPostProcessors真是坑麻车,第一次看到這里的時(shí)候,愣住了斗这,總覺得獲得的永遠(yuǎn)都是空的集合动猬,掉入坑里,久久無(wú)法自拔
        //后來才知道spring允許我們手動(dòng)添加BeanFactoryPostProcessor
        //即:annotationConfigApplicationContext.addBeanFactoryPostProcessor(XXX);
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

        // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
        // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }

讓我們看看第一個(gè)小方法的第二個(gè)參數(shù):

    public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
        return this.beanFactoryPostProcessors;
    }

這里獲得的是BeanFactoryPostProcessor表箭,當(dāng)我看到這里的時(shí)候赁咙,愣住了,通過IDEA的查找引用功能免钻,我發(fā)現(xiàn)這個(gè)集合永遠(yuǎn)都是空的彼水,根本沒有代碼為這個(gè)集合添加數(shù)據(jù),很久都沒有想通极舔,后來才知道我們?cè)谕獠靠梢允謩?dòng)添加一個(gè)后置處理器凤覆,而不是交給Spring去掃描,即:

        AnnotationConfigApplicationContext annotationConfigApplicationContext =
                new AnnotationConfigApplicationContext(AppConfig.class);
        annotationConfigApplicationContext.addBeanFactoryPostProcessor(XXX);

只有這樣姆怪,這個(gè)集合才不會(huì)為空叛赚,但是應(yīng)該沒有人這么做吧,當(dāng)然也有可能是我孤陋寡聞稽揭。

讓我們點(diǎn)開invokeBeanFactoryPostProcessors方法:

    public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set<String> processedBeans = new HashSet<>();

        //beanFactory是DefaultListableBeanFactory俺附,是BeanDefinitionRegistry的實(shí)現(xiàn)類,所以肯定滿足if
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;

            //regularPostProcessors 用來存放BeanFactoryPostProcessor溪掀,
            List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();

            //registryProcessors 用來存放BeanDefinitionRegistryPostProcessor
            //BeanDefinitionRegistryPostProcessor擴(kuò)展了BeanFactoryPostProcessor
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

            // 循環(huán)傳進(jìn)來的beanFactoryPostProcessors事镣,正常情況下,beanFactoryPostProcessors肯定沒有數(shù)據(jù)
            // 因?yàn)閎eanFactoryPostProcessors是獲得手動(dòng)添加的揪胃,而不是spring掃描的
            // 只有手動(dòng)調(diào)用annotationConfigApplicationContext.addBeanFactoryPostProcessor(XXX)才會(huì)有數(shù)據(jù)
            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                // 判斷postProcessor是不是BeanDefinitionRegistryPostProcessor璃哟,因?yàn)锽eanDefinitionRegistryPostProcessor
                // 擴(kuò)展了BeanFactoryPostProcessor,所以這里先要判斷是不是BeanDefinitionRegistryPostProcessor
                // 是的話喊递,直接執(zhí)行postProcessBeanDefinitionRegistry方法随闪,然后把對(duì)象裝到registryProcessors里面去
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }

                else {//不是的話,就裝到regularPostProcessors
                    regularPostProcessors.add(postProcessor);
                }
            }

            // Do not initialize FactoryBeans here: We need to leave all regular beans
            // uninitialized to let the bean factory post-processors apply to them!
            // Separate between BeanDefinitionRegistryPostProcessors that implement
            // PriorityOrdered, Ordered, and the rest.
            //一個(gè)臨時(shí)變量骚勘,用來裝載BeanDefinitionRegistryPostProcessor
            //BeanDefinitionRegistry繼承了PostProcessorBeanFactoryPostProcessor
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

            // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            // 獲得實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口的類的BeanName:org.springframework.context.annotation.internalConfigurationAnnotationProcessor
            // 并且裝入數(shù)組postProcessorNames铐伴,我理解一般情況下,只會(huì)找到一個(gè)
            // 這里又有一個(gè)坑俏讹,為什么我自己創(chuàng)建了一個(gè)實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口的類当宴,也打上了@Component注解
            // 配置類也加上了@Component注解,但是這里卻沒有拿到
            // 因?yàn)橹钡竭@一步泽疆,Spring還沒有去掃描户矢,掃描是在ConfigurationClassPostProcessor類中完成的,也就是下面的第一個(gè)
            // invokeBeanDefinitionRegistryPostProcessors方法
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

            for (String ppName : postProcessorNames) {
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    //獲得ConfigurationClassPostProcessor類殉疼,并且放到currentRegistryProcessors
                    //ConfigurationClassPostProcessor是很重要的一個(gè)類梯浪,它實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor接口
                    //BeanDefinitionRegistryPostProcessor接口又實(shí)現(xiàn)了BeanFactoryPostProcessor接口
                    //ConfigurationClassPostProcessor是極其重要的類
                    //里面執(zhí)行了掃描Bean捌年,Import,ImportResouce等各種操作
                    //用來處理配置類(有兩種情況 一種是傳統(tǒng)意義上的配置類驱证,一種是普通的bean)的各種邏輯
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    //把name放到processedBeans延窜,后續(xù)會(huì)根據(jù)這個(gè)集合來判斷處理器是否已經(jīng)被執(zhí)行過了
                    processedBeans.add(ppName);
                }
            }

            //處理排序
            sortPostProcessors(currentRegistryProcessors, beanFactory);

            //合并Processors,為什么要合并抹锄,因?yàn)閞egistryProcessors是裝載BeanDefinitionRegistryPostProcessor的
            //一開始的時(shí)候逆瑞,spring只會(huì)執(zhí)行BeanDefinitionRegistryPostProcessor獨(dú)有的方法
            //而不會(huì)執(zhí)行BeanDefinitionRegistryPostProcessor父類的方法,即BeanFactoryProcessor的方法
            //所以這里需要把處理器放入一個(gè)集合中伙单,后續(xù)統(tǒng)一執(zhí)行父類的方法
            registryProcessors.addAll(currentRegistryProcessors);

            //可以理解為執(zhí)行ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
            //Spring熱插播的體現(xiàn)获高,像ConfigurationClassPostProcessor就相當(dāng)于一個(gè)組件,Spring很多事情就是交給組件去管理
            //如果不想用這個(gè)組件吻育,直接把注冊(cè)組件的那一步去掉就可以
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

            //因?yàn)閏urrentRegistryProcessors是一個(gè)臨時(shí)變量念秧,所以需要清除
            currentRegistryProcessors.clear();

            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            // 再次根據(jù)BeanDefinitionRegistryPostProcessor獲得BeanName,看這個(gè)BeanName是否已經(jīng)被執(zhí)行過了布疼,有沒有實(shí)現(xiàn)Ordered接口
            // 如果沒有被執(zhí)行過摊趾,也實(shí)現(xiàn)了Ordered接口的話,把對(duì)象推送到currentRegistryProcessors游两,名稱推送到processedBeans
            // 如果沒有實(shí)現(xiàn)Ordered接口的話砾层,這里不把數(shù)據(jù)加到currentRegistryProcessors,processedBeans中贱案,后續(xù)再做處理
            // 這里才可以獲得我們定義的實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor的Bean
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }

            //處理排序
            sortPostProcessors(currentRegistryProcessors, beanFactory);

            //合并Processors
            registryProcessors.addAll(currentRegistryProcessors);

            //執(zhí)行我們自定義的BeanDefinitionRegistryPostProcessor
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

            //清空臨時(shí)變量
            currentRegistryProcessors.clear();

            // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            // 上面的代碼是執(zhí)行了實(shí)現(xiàn)了Ordered接口的BeanDefinitionRegistryPostProcessor肛炮,
            // 下面的代碼就是執(zhí)行沒有實(shí)現(xiàn)Ordered接口的BeanDefinitionRegistryPostProcessor
            boolean reiterate = true;
            while (reiterate) {
                reiterate = false;
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }

            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
            //registryProcessors集合裝載BeanDefinitionRegistryPostProcessor
            //上面的代碼是執(zhí)行子類獨(dú)有的方法,這里需要再把父類的方法也執(zhí)行一次
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);

            //regularPostProcessors裝載BeanFactoryPostProcessor宝踪,執(zhí)行BeanFactoryPostProcessor的方法
            //但是regularPostProcessors一般情況下侨糟,是不會(huì)有數(shù)據(jù)的,只有在外面手動(dòng)添加BeanFactoryPostProcessor瘩燥,才會(huì)有數(shù)據(jù)
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }

        else {
            // Invoke factory processors registered with the context instance.
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        //找到BeanFactoryPostProcessor實(shí)現(xiàn)類的BeanName數(shù)組
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        //循環(huán)BeanName數(shù)組
        for (String ppName : postProcessorNames) {
            //如果這個(gè)Bean被執(zhí)行過了秕重,跳過
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            }
            //如果實(shí)現(xiàn)了PriorityOrdered接口,加入到priorityOrderedPostProcessors
            else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }
            //如果實(shí)現(xiàn)了Ordered接口厉膀,加入到orderedPostProcessorNames
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            //如果既沒有實(shí)現(xiàn)PriorityOrdered悲幅,也沒有實(shí)現(xiàn)Ordered。加入到nonOrderedPostProcessorNames
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        //排序處理priorityOrderedPostProcessors站蝠,即實(shí)現(xiàn)了PriorityOrdered接口的BeanFactoryPostProcessor
        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        //執(zhí)行priorityOrderedPostProcessors
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        //執(zhí)行實(shí)現(xiàn)了Ordered接口的BeanFactoryPostProcessor
        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
        for (String postProcessorName : orderedPostProcessorNames) {
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        // 執(zhí)行既沒有實(shí)現(xiàn)PriorityOrdered接口,也沒有實(shí)現(xiàn)Ordered接口的BeanFactoryPostProcessor
        // Finally, invoke all other BeanFactoryPostProcessors.
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

        // Clear cached merged bean definitions since the post-processors might have
        // modified the original metadata, e.g. replacing placeholders in values...
        beanFactory.clearMetadataCache();
    }

首先判斷beanFactory是不是BeanDefinitionRegistry的實(shí)例卓鹿,當(dāng)然肯定是的菱魔,然后執(zhí)行如下操作:

  1. 定義了一個(gè)Set,裝載BeanName吟孙,后面會(huì)根據(jù)這個(gè)Set澜倦,來判斷后置處理器是否被執(zhí)行過了聚蝶。

  2. 定義了兩個(gè)List,一個(gè)是regularPostProcessors藻治,用來裝載BeanFactoryPostProcessor碘勉,一個(gè)是registryProcessors用來裝載BeanDefinitionRegistryPostProcessor,其中BeanDefinitionRegistryPostProcessor擴(kuò)展了BeanFactoryPostProcessor桩卵。BeanDefinitionRegistryPostProcessor有兩個(gè)方法验靡,一個(gè)是獨(dú)有的postProcessBeanDefinitionRegistry方法,一個(gè)是父類的postProcessBeanFactory方法雏节。

  3. 循環(huán)傳進(jìn)來的beanFactoryPostProcessors胜嗓,上面已經(jīng)解釋過了,一般情況下钩乍,這里永遠(yuǎn)都是空的辞州,只有手動(dòng)add beanFactoryPostProcessor,這里才會(huì)有數(shù)據(jù)寥粹。我們假設(shè)beanFactoryPostProcessors有數(shù)據(jù)变过,進(jìn)入循環(huán),判斷postProcessor是不是BeanDefinitionRegistryPostProcessor涝涤,因?yàn)锽eanDefinitionRegistryPostProcessor擴(kuò)展了BeanFactoryPostProcessor媚狰,所以這里先要判斷是不是BeanDefinitionRegistryPostProcessor,是的話妄痪,執(zhí)行postProcessBeanDefinitionRegistry方法哈雏,然后把對(duì)象裝到registryProcessors里面去,不是的話衫生,就裝到regularPostProcessors裳瘪。

  4. 定義了一個(gè)臨時(shí)變量:currentRegistryProcessors,用來裝載BeanDefinitionRegistryPostProcessor罪针。

  5. getBeanNamesForType彭羹,顧名思義,是根據(jù)類型查到BeanNames泪酱,這里有一點(diǎn)需要注意派殷,就是去哪里找,點(diǎn)開這個(gè)方法的話墓阀,就知道是循環(huán)beanDefinitionNames去找毡惜,這個(gè)方法以后也會(huì)經(jīng)常看到斯撮。這里傳了BeanDefinitionRegistryPostProcessor.class经伙,就是找到類型為BeanDefinitionRegistryPostProcessor的后置處理器,并且賦值給postProcessorNames勿锅。一般情況下帕膜,只會(huì)找到一個(gè)枣氧,就是org.springframework.context.annotation.internalConfigurationAnnotationProcessor,也就是ConfigurationAnnotationProcessor垮刹。這個(gè)后置處理器在上一節(jié)中已經(jīng)說明過了达吞,十分重要。這里有一個(gè)問題荒典,為什么我自己寫了個(gè)類酪劫,實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor接口,也打上了@Component注解种蝶,但是這里沒有獲得契耿,因?yàn)橹钡竭@一步,Spring還沒有完成掃描螃征,掃描是在ConfigurationClassPostProcessor類中完成的搪桂,也就是下面第一個(gè)invokeBeanDefinitionRegistryPostProcessors方法。

  6. 循環(huán)postProcessorNames盯滚,其實(shí)也就是org.springframework.context.annotation.internalConfigurationAnnotationProcessor踢械,判斷此后置處理器是否實(shí)現(xiàn)了PriorityOrdered接口(ConfigurationAnnotationProcessor也實(shí)現(xiàn)了PriorityOrdered接口),
    如果實(shí)現(xiàn)了魄藕,把它添加到currentRegistryProcessors這個(gè)臨時(shí)變量中内列,再放入processedBeans,代表這個(gè)后置處理已經(jīng)被處理過了背率。當(dāng)然現(xiàn)在還沒有處理话瞧,但是馬上就要處理了。寝姿。交排。

  7. 進(jìn)行排序,PriorityOrdered是一個(gè)排序接口饵筑,如果實(shí)現(xiàn)了它埃篓,就說明此后置處理器是有順序的,所以需要排序根资。當(dāng)然目前這里只有一個(gè)后置處理器架专,就是ConfigurationClassPostProcessor。

  8. 把currentRegistryProcessors合并到registryProcessors玄帕,為什么需要合并部脚?因?yàn)橐婚_始spring只會(huì)執(zhí)行BeanDefinitionRegistryPostProcessor獨(dú)有的方法,而不會(huì)執(zhí)行BeanDefinitionRegistryPostProcessor父類的方法裤纹,即BeanFactoryProcessor接口中的方法睛低,所以需要把這些后置處理器放入一個(gè)集合中,后續(xù)統(tǒng)一執(zhí)行BeanFactoryProcessor接口中的方法。當(dāng)然目前這里只有一個(gè)后置處理器钱雷,就是ConfigurationClassPostProcessor。

  9. 可以理解為執(zhí)行currentRegistryProcessors中的ConfigurationClassPostProcessor中的postProcessBeanDefinitionRegistry方法吹零,這就是Spring設(shè)計(jì)思想的體現(xiàn)了罩抗,在這里體現(xiàn)的就是其中的熱插拔,插件化開發(fā)的思想灿椅。Spring中很多東西都是交給插件去處理的套蒂,這個(gè)后置處理器就相當(dāng)于一個(gè)插件,如果不想用了茫蛹,直接不添加就是了操刀。這個(gè)方法特別重要,我們后面會(huì)詳細(xì)說來婴洼。

  10. 清空currentRegistryProcessors骨坑,因?yàn)閏urrentRegistryProcessors是一個(gè)臨時(shí)變量,已經(jīng)完成了目前的使命柬采,所以需要清空欢唾,當(dāng)然后面還會(huì)用到。

  11. 再次根據(jù)BeanDefinitionRegistryPostProcessor獲得BeanName粉捻,然后進(jìn)行循環(huán)礁遣,看這個(gè)后置處理器是否被執(zhí)行過了,如果沒有被執(zhí)行過肩刃,也實(shí)現(xiàn)了Ordered接口的話祟霍,把此后置處理器推送到currentRegistryProcessors和processedBeans中。
    這里就可以獲得我們定義的盈包,并且打上@Component注解的后置處理器了沸呐,因?yàn)镾pring已經(jīng)完成了掃描,但是這里需要注意的是续语,由于ConfigurationClassPostProcessor在上面已經(jīng)被執(zhí)行過了垂谢,所以雖然可以通過getBeanNamesForType獲得,但是并不會(huì)加入到currentRegistryProcessors和processedBeans疮茄。

  12. 處理排序滥朱。

  13. 合并Processors,合并的理由和上面是一樣的力试。

  14. 執(zhí)行我們自定義的BeanDefinitionRegistryPostProcessor徙邻。

  15. 清空臨時(shí)變量。

  16. 在上面的方法中畸裳,僅僅是執(zhí)行了實(shí)現(xiàn)了Ordered接口的BeanDefinitionRegistryPostProcessor缰犁,這里是執(zhí)行沒有實(shí)現(xiàn)Ordered接口的BeanDefinitionRegistryPostProcessor。

  17. 上面的代碼是執(zhí)行子類獨(dú)有的方法,這里需要再把父類的方法也執(zhí)行一次帅容。

  18. 執(zhí)行regularPostProcessors中的后置處理器的方法颇象,需要注意的是,在一般情況下并徘,regularPostProcessors是不會(huì)有數(shù)據(jù)的遣钳,只有在外面手動(dòng)添加BeanFactoryPostProcessor,才會(huì)有數(shù)據(jù)麦乞。

  19. 查找實(shí)現(xiàn)了BeanFactoryPostProcessor的后置處理器蕴茴,并且執(zhí)行后置處理器中的方法。和上面的邏輯差不多姐直,不再詳細(xì)說明倦淀。

這就是這個(gè)方法中做的主要的事情了,可以說是比較復(fù)雜的声畏。但是邏輯還是比較清晰的撞叽,在第9步的時(shí)候,我說有一個(gè)方法會(huì)詳細(xì)說來砰识,現(xiàn)在就讓我們好好看看這個(gè)方法究竟做了什么吧能扒。

    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
        String[] candidateNames = registry.getBeanDefinitionNames();//獲得所有的BeanDefinition的Name,放入candidateNames數(shù)組

        //循環(huán)candidateNames數(shù)組
        for (String beanName : candidateNames) {
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);//根據(jù)beanName獲得BeanDefinition

            // 內(nèi)部有兩個(gè)標(biāo)記位來標(biāo)記是否已經(jīng)處理過了
            // 這里會(huì)引發(fā)一連串知識(shí)盲點(diǎn)
            // 當(dāng)我們注冊(cè)配置類的時(shí)候辫狼,可以不加Configuration注解初斑,直接使用Component ComponentScan Import ImportResource注解,稱之為L(zhǎng)ite配置類
            // 如果加了Configuration注解膨处,就稱之為Full配置類
            // 如果我們注冊(cè)了Lite配置類见秤,我們getBean這個(gè)配置類,會(huì)發(fā)現(xiàn)它就是原本的那個(gè)配置類
            // 如果我們注冊(cè)了Full配置類真椿,我們getBean這個(gè)配置類鹃答,會(huì)發(fā)現(xiàn)它已經(jīng)不是原本那個(gè)配置類了,而是已經(jīng)被cgilb代理的類了
            // 寫一個(gè)A類突硝,其中有一個(gè)構(gòu)造方法测摔,打印出“你好”
            // 再寫一個(gè)配置類,里面有兩個(gè)bean注解的方法
            // 其中一個(gè)方法new了A 類解恰,并且返回A的對(duì)象锋八,把此方法稱之為getA
            // 第二個(gè)方法又調(diào)用了getA方法
            // 如果配置類是Lite配置類,會(huì)發(fā)現(xiàn)打印了兩次“你好”护盈,也就是說A類被new了兩次
            // 如果配置類是Full配置類挟纱,會(huì)發(fā)現(xiàn)只打印了一次“你好”,也就是說A類只被new了一次腐宋,因?yàn)檫@個(gè)類被cgilb代理了紊服,方法已經(jīng)被改寫
            if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
                    ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                }
            }

            //判斷是否為配置類(有兩種情況 一種是傳統(tǒng)意義上的配置類檀轨,一種是普通的bean),
            //在這個(gè)方法內(nèi)部欺嗤,會(huì)做判斷参萄,這個(gè)配置類是Full配置類,還是Lite配置類煎饼,并且做上標(biāo)記
            //滿足條件拧揽,加入到configCandidates
            else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }

        // 如果沒有配置類,直接返回
        // Return immediately if no @Configuration classes were found
        if (configCandidates.isEmpty()) {
            return;
        }

        // Sort by previously determined @Order value, if applicable
        //處理排序
        configCandidates.sort((bd1, bd2) -> {
            int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
            int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
            return Integer.compare(i1, i2);
        });

        // Detect any custom bean name generation strategy supplied through the enclosing application context
        SingletonBeanRegistry sbr = null;
        // DefaultListableBeanFactory最終會(huì)實(shí)現(xiàn)SingletonBeanRegistry接口腺占,所以可以進(jìn)入到這個(gè)if
        if (registry instanceof SingletonBeanRegistry) {
            sbr = (SingletonBeanRegistry) registry;
            if (!this.localBeanNameGeneratorSet) {
                //spring中可以修改默認(rèn)的bean命名方式,這里就是看用戶有沒有自定義bean命名方式痒谴,雖然一般沒有人會(huì)這么做
                BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
                if (generator != null) {
                    this.componentScanBeanNameGenerator = generator;
                    this.importBeanNameGenerator = generator;
                }
            }
        }

        if (this.environment == null) {
            this.environment = new StandardEnvironment();
        }

        // Parse each @Configuration class
        ConfigurationClassParser parser = new ConfigurationClassParser(
                this.metadataReaderFactory, this.problemReporter, this.environment,
                this.resourceLoader, this.componentScanBeanNameGenerator, registry);

        Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
        Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
        do {
            //解析配置類(傳統(tǒng)意義上的配置類或者是普通bean衰伯,核心來了)
            parser.parse(candidates);
            parser.validate();

            Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
            configClasses.removeAll(alreadyParsed);

            // Read the model and create bean definitions based on its content
            if (this.reader == null) {
                this.reader = new ConfigurationClassBeanDefinitionReader(
                        registry, this.sourceExtractor, this.resourceLoader, this.environment,
                        this.importBeanNameGenerator, parser.getImportRegistry());
            }
            this.reader.loadBeanDefinitions(configClasses);//直到這一步才把Import的類,@Bean @ImportRosource 轉(zhuǎn)換成BeanDefinition
            alreadyParsed.addAll(configClasses);//把configClasses加入到alreadyParsed积蔚,代表

            candidates.clear();
            //獲得注冊(cè)器里面BeanDefinition的數(shù)量 和 candidateNames進(jìn)行比較
            //如果大于的話意鲸,說明有新的BeanDefinition注冊(cè)進(jìn)來了
            if (registry.getBeanDefinitionCount() > candidateNames.length) {
                String[] newCandidateNames = registry.getBeanDefinitionNames();//從注冊(cè)器里面獲得BeanDefinitionNames
                Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));//candidateNames轉(zhuǎn)換set
                Set<String> alreadyParsedClasses = new HashSet<>();
                //循環(huán)alreadyParsed。把類名加入到alreadyParsedClasses
                for (ConfigurationClass configurationClass : alreadyParsed) {
                    alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
                }
                for (String candidateName : newCandidateNames) {
                    if (!oldCandidateNames.contains(candidateName)) {
                        BeanDefinition bd = registry.getBeanDefinition(candidateName);
                        if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                                !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                            candidates.add(new BeanDefinitionHolder(bd, candidateName));
                        }
                    }
                }
                candidateNames = newCandidateNames;
            }
        }
        while (!candidates.isEmpty());

        // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
        if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
            sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
        }

        if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
            // Clear cache in externally provided MetadataReaderFactory; this is a no-op
            // for a shared cache since it'll be cleared by the ApplicationContext.
            ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
        }
    }
  1. 獲得所有的BeanName尽爆,放入candidateNames數(shù)組怎顾。
  2. 循環(huán)candidateNames數(shù)組,根據(jù)beanName獲得BeanDefinition漱贱,判斷此BeanDefinition是否已經(jīng)被處理過了槐雾。
  3. 判斷是否是配置類,如果是的話幅狮。加入到configCandidates數(shù)組募强,在判斷的時(shí)候,還會(huì)標(biāo)記配置類屬于Full配置類崇摄,還是Lite配置類擎值,這里會(huì)引發(fā)一連串的知識(shí)盲點(diǎn):
    3.1 當(dāng)我們注冊(cè)配置類的時(shí)候,可以不加@Configuration注解逐抑,直接使用@Component @ComponentScan @Import @ImportResource等注解鸠儿,Spring把這種配置類稱之為L(zhǎng)ite配置類, 如果加了@Configuration注解厕氨,就稱之為Full配置類进每。
    3.2 如果我們注冊(cè)了Lite配置類,我們getBean這個(gè)配置類腐巢,會(huì)發(fā)現(xiàn)它就是原本的那個(gè)配置類品追,如果我們注冊(cè)了Full配置類,我們getBean這個(gè)配置類冯丙,會(huì)發(fā)現(xiàn)它已經(jīng)不是原本那個(gè)配置類了肉瓦,而是已經(jīng)被cgilb代理的類了遭京。
    3.3 寫一個(gè)A類,其中有一個(gè)構(gòu)造方法泞莉,打印出“你好”哪雕,再寫一個(gè)配置類,里面有兩個(gè)被@bean注解的方法鲫趁,其中一個(gè)方法new了A類斯嚎,并且返回A的對(duì)象,把此方法稱之為getA挨厚,第二個(gè)方法又調(diào)用了getA方法堡僻,如果配置類是Lite配置類,會(huì)發(fā)現(xiàn)打印了兩次“你好”疫剃,也就是說A類被new了兩次钉疫,如果配置類是Full配置類,會(huì)發(fā)現(xiàn)只打印了一次“你好”巢价,也就是說A類只被new了一次牲阁,因?yàn)檫@個(gè)類被cgilb代理了,方法已經(jīng)被改寫壤躲。
    3.4 具體的可以看我的這篇博客:http://www.reibang.com/p/d001f96933cf城菊,里面有詳細(xì)的說明。
  4. 如果沒有配置類直接返回碉克。
  5. 處理排序凌唬。
  6. 解析配置類,可能是Full配置類棉胀,也有可能是Lite配置類法瑟,這個(gè)小方法是此方法的核心,稍后具體說明唁奢。
  7. 在第6步的時(shí)候霎挟,只是注冊(cè)了部分Bean,像 @Import @Bean等麻掸,是沒有被注冊(cè)的酥夭,這里統(tǒng)一對(duì)這些進(jìn)行注冊(cè)。

下面是解析配置類的過程:

    public void parse(Set<BeanDefinitionHolder> configCandidates) {
        this.deferredImportSelectors = new LinkedList<>();
        //循環(huán)傳進(jìn)來的配置類
        for (BeanDefinitionHolder holder : configCandidates) {
            BeanDefinition bd = holder.getBeanDefinition();//獲得BeanDefinition
            try {
                //如果獲得BeanDefinition是AnnotatedBeanDefinition的實(shí)例
                if (bd instanceof AnnotatedBeanDefinition) {
                    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);
            }
        }

        //執(zhí)行DeferredImportSelector
        processDeferredImportSelectors();
    }

因?yàn)榭梢杂卸鄠€(gè)配置類脊奋,所以需要循環(huán)處理描睦。我們的配置類的BeanDefinition是AnnotatedBeanDefinition的實(shí)例幔烛,所以會(huì)進(jìn)入第一個(gè)if:

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
        processConfigurationClass(new ConfigurationClass(metadata, beanName));
    }
    protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {

        //判斷是否需要跳過
        if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
            return;
        }

        ConfigurationClass existingClass = this.configurationClasses.get(configClass);
        if (existingClass != null) {
            if (configClass.isImported()) {
                if (existingClass.isImported()) {
                    existingClass.mergeImportedBy(configClass);
                }
                // Otherwise ignore new imported config class; existing non-imported class overrides it.
                return;
            } else {
                // Explicit bean definition found, probably replacing an import.
                // Let's remove the old one and go with the new one.
                this.configurationClasses.remove(configClass);
                this.knownSuperclasses.values().removeIf(configClass::equals);
            }
        }

        // Recursively process the configuration class and its superclass hierarchy.
        SourceClass sourceClass = asSourceClass(configClass);
        do {
            sourceClass = doProcessConfigurationClass(configClass, sourceClass);
        }
        while (sourceClass != null);

        this.configurationClasses.put(configClass, configClass);
    }

重點(diǎn)在于doProcessConfigurationClass方法嗡贺,需要特別注意赎懦,最后一行代碼,會(huì)把configClass放入一個(gè)Map久又,會(huì)在上面第7步中用到巫延。

    protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
            throws IOException {

        //遞歸處理內(nèi)部類效五,一般不會(huì)寫內(nèi)部類
        // Recursively process any member (nested) classes first
        processMemberClasses(configClass, sourceClass);

        // Process any @PropertySource annotations
        //處理@PropertySource注解,@PropertySource注解用來加載properties文件
        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");
            }
        }

        // Process any @ComponentScan annotations
        //獲得ComponentScan注解具體的內(nèi)容炉峰,ComponentScan注解除了最常用的basePackage之外畏妖,還有includeFilters,excludeFilters等
        Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
                sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);

        //如果沒有打上ComponentScan疼阔,或者被@Condition條件跳過戒劫,就不再進(jìn)入這個(gè)if
        if (!componentScans.isEmpty() &&
                !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
            //循環(huán)處理componentScans
            for (AnnotationAttributes componentScan : componentScans) {
                // The config class is annotated with @ComponentScan -> perform the scan immediately
                //componentScan就是@ComponentScan上的具體內(nèi)容,sourceClass.getMetadata().getClassName()就是配置類的名稱
                Set<BeanDefinitionHolder> scannedBeanDefinitions =
                        this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                // Check the set of scanned definitions for any further config classes and parse recursively if needed
                for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                    if (bdCand == null) {
                        bdCand = holder.getBeanDefinition();
                    }
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                        //遞歸調(diào)用婆廊,因?yàn)榭赡芙M件類有被@Bean標(biāo)記的方法迅细,或者組件類本身也有ComponentScan等注解
                        parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }

        // Process any @Import annotations
        //處理@Import注解
        //@Import注解是spring中很重要的一個(gè)注解,Springboot大量應(yīng)用這個(gè)注解
        //@Import三種類淘邻,一種是Import普通類疯攒,一種是Import ImportSelector,還有一種是Import ImportBeanDefinitionRegistrar
        //getImports(sourceClass)是獲得import的內(nèi)容列荔,返回的是一個(gè)set
        processImports(configClass, sourceClass, getImports(sourceClass), true);

        // Process any @ImportResource annotations
        //處理@ImportResource注解
        AnnotationAttributes importResource =
                AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
        if (importResource != null) {
            String[] resources = importResource.getStringArray("locations");
            Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
            for (String resource : resources) {
                String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
                configClass.addImportedResource(resolvedResource, readerClass);
            }
        }

        //處理@Bean的方法,可以看到獲得了帶有@Bean的方法后枚尼,不是馬上轉(zhuǎn)換成BeanDefinition贴浙,而是先用一個(gè)set接收
        // Process individual @Bean methods
        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
        for (MethodMetadata methodMetadata : beanMethods) {
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }

        // Process default methods on interfaces
        processInterfaces(configClass, sourceClass);

        // Process superclass, if any
        if (sourceClass.getMetadata().hasSuperClass()) {
            String superclass = sourceClass.getMetadata().getSuperClassName();
            if (superclass != null && !superclass.startsWith("java") &&
                    !this.knownSuperclasses.containsKey(superclass)) {
                this.knownSuperclasses.put(superclass, configClass);
                // Superclass found, return its annotation metadata and recurse
                return sourceClass.getSuperClass();
            }
        }

        // No superclass -> processing is complete
        return null;
    }
  1. 遞歸處理內(nèi)部類,一般不會(huì)使用內(nèi)部類署恍。
  2. 處理@PropertySource注解崎溃,@PropertySource注解用來加載properties文件。
  3. 獲得ComponentScan注解具體的內(nèi)容盯质,ComponentScan注解除了最常用的basePackage之外袁串,還有includeFilters,excludeFilters等呼巷。
  4. 判斷有沒有被@ComponentScans標(biāo)記囱修,或者被@Condition條件帶過,如果滿足條件的話王悍,進(jìn)入if破镰,進(jìn)行如下操作:
    4.1 執(zhí)行掃描操作,把掃描出來的放入set压储,這個(gè)方法稍后再詳細(xì)說明鲜漩。
    4.2 循環(huán)set,判斷是否是配置類集惋,是的話孕似,遞歸調(diào)用parse方法,因?yàn)楸粧呙璩鰜淼念惞涡蹋€是一個(gè)配置類喉祭,有@ComponentScans注解养渴,或者其中有被@Bean標(biāo)記的方法 等等,所以需要再次被解析臂拓。
  5. 處理@Import注解厚脉,@Import是Spring中很重要的一個(gè)注解,正是由于它的存在胶惰,讓Spring非常靈活傻工,不管是Spring內(nèi)部,還是與Spring整合的第三方技術(shù)孵滞,都大量的運(yùn)用了@Import注解中捆,@Import有三種情況,一種是Import普通類坊饶,一種是Import ImportSelector泄伪,還有一種是Import ImportBeanDefinitionRegistrar,getImports(sourceClass)是獲得import的內(nèi)容匿级,返回的是一個(gè)set蟋滴,這個(gè)方法稍后再詳細(xì)說明。
  6. 處理@ImportResource注解痘绎。
  7. 處理@Bean的方法津函,可以看到獲得了帶有@Bean的方法后,不是馬上轉(zhuǎn)換成BeanDefinition孤页,而是先用一個(gè)set接收尔苦。

我們先來看4.1中的那個(gè)方法:

    public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
        //掃描器,還記不記在new AnnotationConfigApplicationContext的時(shí)候
        //會(huì)調(diào)用AnnotationConfigApplicationContext的構(gòu)造方法
        //構(gòu)造方法里面有一句 this.scanner = new ClassPathBeanDefinitionScanner(this);
        //當(dāng)時(shí)說這個(gè)對(duì)象不重要行施,這里就是證明了允坚。常規(guī)用法中,實(shí)際上執(zhí)行掃描的只會(huì)是這里的scanner對(duì)象
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
                componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

        //判斷是否重寫了默認(rèn)的命名規(guī)則
        Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
        boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
        scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
                BeanUtils.instantiateClass(generatorClass));

        ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
        if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
            scanner.setScopedProxyMode(scopedProxyMode);
        }
        else {
            Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
            scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
        }

        scanner.setResourcePattern(componentScan.getString("resourcePattern"));

        //addIncludeFilter addExcludeFilter,最終是往List<TypeFilter>里面填充數(shù)據(jù)
        //TypeFilter是一個(gè)函數(shù)式接口蛾号,函數(shù)式接口在java8的時(shí)候大放異彩稠项,只定義了一個(gè)虛方法的接口被稱為函數(shù)式接口
        //當(dāng)調(diào)用scanner.addIncludeFilter  scanner.addExcludeFilter 僅僅把 定義的規(guī)則塞進(jìn)去,并么有真正去執(zhí)行匹配過程

        //處理includeFilters
        for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
            for (TypeFilter typeFilter : typeFiltersFor(filter)) {
                scanner.addIncludeFilter(typeFilter);
            }
        }

        //處理excludeFilters
        for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
            for (TypeFilter typeFilter : typeFiltersFor(filter)) {
                scanner.addExcludeFilter(typeFilter);
            }
        }

        boolean lazyInit = componentScan.getBoolean("lazyInit");
        if (lazyInit) {
            scanner.getBeanDefinitionDefaults().setLazyInit(true);
        }

        Set<String> basePackages = new LinkedHashSet<>();
        String[] basePackagesArray = componentScan.getStringArray("basePackages");
        for (String pkg : basePackagesArray) {
            String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
                    ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
            Collections.addAll(basePackages, tokenized);
        }
        // 從下面的代碼可以看出ComponentScans指定掃描目標(biāo)鲜结,除了最常用的basePackages皿渗,還有兩種方式
        // 1.指定basePackageClasses,就是指定多個(gè)類轻腺,只要是與這幾個(gè)類同級(jí)的乐疆,或者在這幾個(gè)類下級(jí)的都可以被掃描到,這種方式其實(shí)是spring比較推薦的
        // 因?yàn)橹付╞asePackages沒有IDE的檢查贬养,容易出錯(cuò)挤土,但是指定一個(gè)類,就有IDE的檢查了误算,不容易出錯(cuò)仰美,經(jīng)常會(huì)用一個(gè)空的類來作為basePackageClasses
        // 2.直接不指定迷殿,默認(rèn)會(huì)把與配置類同級(jí),或者在配置類下級(jí)的作為掃描目標(biāo)
        for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
            basePackages.add(ClassUtils.getPackageName(clazz));
        }
        if (basePackages.isEmpty()) {
            basePackages.add(ClassUtils.getPackageName(declaringClass));
        }

        //把規(guī)則填充到排除規(guī)則:List<TypeFilter>咖杂,這里就把 注冊(cè)類自身當(dāng)作排除規(guī)則庆寺,真正執(zhí)行匹配的時(shí)候,會(huì)把自身給排除
        scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
            @Override
            protected boolean matchClassName(String className) {
                return declaringClass.equals(className);
            }
        });
        //basePackages是一個(gè)LinkedHashSet<String>诉字,這里就是把basePackages轉(zhuǎn)為字符串?dāng)?shù)組的形式
        return scanner.doScan(StringUtils.toStringArray(basePackages));
    }
  1. 定義了一個(gè)掃描器scanner懦尝,還記不記在new AnnotationConfigApplicationContext的時(shí)候,會(huì)調(diào)用AnnotationConfigApplicationContext的構(gòu)造方法壤圃,構(gòu)造方法里面有一句 this.scanner = new ClassPathBeanDefinitionScanner(this);當(dāng)時(shí)說這個(gè)對(duì)象不重要陵霉,這里就是證明了。常規(guī)用法中伍绳,實(shí)際上執(zhí)行掃描的只會(huì)是這里的scanner對(duì)象踊挠。
  2. 處理includeFilters,就是把規(guī)則添加到scanner冲杀。
  3. 處理excludeFilters效床,就是把規(guī)則添加到scanner。
  4. 解析basePackages权谁,獲得需要掃描哪些包扁凛。
  5. 添加一個(gè)默認(rèn)的排除規(guī)則:排除自身。
  6. 執(zhí)行掃描闯传,稍后詳細(xì)說明。

這里需要做一個(gè)補(bǔ)充說明卤妒,添加規(guī)則的時(shí)候甥绿,只是把具體的規(guī)則放入規(guī)則類的集合中去,規(guī)則類是一個(gè)函數(shù)式接口则披,只定義了一個(gè)虛方法的接口被稱為函數(shù)式接口共缕,函數(shù)式接口在java8的時(shí)候大放異彩,這里只是把規(guī)則方塞進(jìn)去士复,并沒有真正執(zhí)行匹配規(guī)則图谷。

我們來看看到底是怎么執(zhí)行掃描的:

    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Assert.notEmpty(basePackages, "At least one base package must be specified");
        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
        //循環(huán)處理basePackages
        for (String basePackage : basePackages) {
            //根據(jù)包名找到符合條件的BeanDefinition集合
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
            for (BeanDefinition candidate : candidates) {
                ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
                candidate.setScope(scopeMetadata.getScopeName());
                String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                //由findCandidateComponents內(nèi)部可知,這里的candidate是ScannedGenericBeanDefinition
                //而ScannedGenericBeanDefinition是AbstractBeanDefinition和AnnotatedBeanDefinition的之類
                //所以下面的兩個(gè)if都會(huì)進(jìn)入
                if (candidate instanceof AbstractBeanDefinition) {
                    //內(nèi)部會(huì)設(shè)置默認(rèn)值
                    postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
                }
                if (candidate instanceof AnnotatedBeanDefinition) {
                    //如果是AnnotatedBeanDefinition阱洪,還會(huì)再設(shè)置一次值
                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
                }
                if (checkCandidate(beanName, candidate)) {
                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                    definitionHolder =
                            AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                    beanDefinitions.add(definitionHolder);
                    registerBeanDefinition(definitionHolder, this.registry);
                }
            }
        }
        return beanDefinitions;
    }

因?yàn)閎asePackages可能有多個(gè)便贵,所以需要循環(huán)處理,最終會(huì)進(jìn)行Bean的注冊(cè)冗荸。下面再來看看findCandidateComponents方法:

    public Set<BeanDefinition> findCandidateComponents(String basePackage) {
        //spring支持component索引技術(shù)承璃,需要引入一個(gè)組件,因?yàn)榇蟛糠智闆r不會(huì)引入這個(gè)組件
        //所以不會(huì)進(jìn)入到這個(gè)if
        if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
            return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
        }
        else {
            return scanCandidateComponents(basePackage);
        }
    }

Spring支持component索引技術(shù)蚌本,需要引入一個(gè)組件盔粹,大部分項(xiàng)目沒有引入這個(gè)組件隘梨,所以會(huì)進(jìn)入scanCandidateComponents方法:

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
        Set<BeanDefinition> candidates = new LinkedHashSet<>();
        try {
            //把 傳進(jìn)來的類似 命名空間形式的字符串轉(zhuǎn)換成類似類文件地址的形式,然后在前面加上classpath*:
            //即:com.xx=>classpath*:com/xx/**/*.class
            String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                    resolveBasePackage(basePackage) + '/' + this.resourcePattern;
            //根據(jù)packageSearchPath舷嗡,獲得符合要求的文件
            Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
            boolean traceEnabled = logger.isTraceEnabled();
            boolean debugEnabled = logger.isDebugEnabled();
            //循環(huán)資源
            for (Resource resource : resources) {
                if (traceEnabled) {
                    logger.trace("Scanning " + resource);
                }

                if (resource.isReadable()) {//判斷資源是否可讀轴猎,并且不是一個(gè)目錄
                    try {
                        //metadataReader 元數(shù)據(jù)讀取器,解析resource进萄,也可以理解為描述資源的數(shù)據(jù)結(jié)構(gòu)
                        MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                        //在isCandidateComponent方法內(nèi)部會(huì)真正執(zhí)行匹配規(guī)則
                        //注冊(cè)配置類自身會(huì)被排除捻脖,不會(huì)進(jìn)入到這個(gè)if
                        if (isCandidateComponent(metadataReader)) {
                            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 (Throwable ex) {
                        throw new BeanDefinitionStoreException(
                                "Failed to read candidate component class: " + resource, ex);
                    }
                }
                else {
                    if (traceEnabled) {
                        logger.trace("Ignored because not readable: " + resource);
                    }
                }
            }
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
        }
        return candidates;
    }
  1. 把傳進(jìn)來的類似命名空間形式的字符串轉(zhuǎn)換成類似類文件地址的形式,然后在前面加上classpath垮斯,即:com.xx=>classpath:com/xx/*/.class郎仆。
  2. 根據(jù)packageSearchPath,獲得符合要求的文件兜蠕。
  3. 循環(huán)符合要求的文件扰肌,進(jìn)一步進(jìn)行判斷。
    最終會(huì)把符合要求的文件熊杨,轉(zhuǎn)換為BeanDefinition曙旭,并且返回。

直到這里晶府,上面說的4.1中提到的方法終于分析完畢了桂躏,讓我們?cè)倏纯瓷厦嫣岬降牡?步中的處理@Import注解方法:

    //這個(gè)方法內(nèi)部相當(dāng)相當(dāng)復(fù)雜,importCandidates是Import的內(nèi)容川陆,調(diào)用這個(gè)方法的時(shí)候剂习,已經(jīng)說過可能有三種情況
    //這里再說下,1.Import普通類较沪,2.Import ImportSelector鳞绕,3.Import ImportBeanDefinitionRegistrar
    //循環(huán)importCandidates,判斷屬于哪種情況
    //如果是普通類尸曼,會(huì)進(jìn)到else们何,調(diào)用processConfigurationClass方法
    //這個(gè)方法是不是很熟悉,沒錯(cuò)控轿,processImports這個(gè)方法就是在processConfigurationClass方法中被調(diào)用的
    //processImports又主動(dòng)調(diào)用processConfigurationClass方法冤竹,是一個(gè)遞歸調(diào)用,因?yàn)镮mport的普通類茬射,也有可能被加了Import注解鹦蠕,@ComponentScan注解 或者其他注解,所以普通類需要再次被解析
    //如果Import ImportSelector就跑到了第一個(gè)if中去在抛,首先執(zhí)行Aware接口方法片部,所以我們?cè)趯?shí)現(xiàn)ImportSelector的同時(shí),還可以實(shí)現(xiàn)Aware接口
    //然后判斷是不是DeferredImportSelector,DeferredImportSelector擴(kuò)展了ImportSelector
    //如果不是的話档悠,調(diào)用selectImports方法廊鸥,獲得全限定類名數(shù)組,在轉(zhuǎn)換成類的數(shù)組辖所,然后再調(diào)用processImports惰说,又特么的是一個(gè)遞歸調(diào)用...
    //可能又有三種情況,一種情況是selectImports的類是一個(gè)普通類缘回,第二種情況是selectImports的類是一個(gè)ImportBeanDefinitionRegistrar類吆视,第三種情況是還是一個(gè)ImportSelector類...
    //所以又需要遞歸調(diào)用
    //如果Import ImportBeanDefinitionRegistrar就跑到了第二個(gè)if,還是會(huì)執(zhí)行Aware接口方法酥宴,這里終于沒有遞歸了啦吧,會(huì)把數(shù)據(jù)放到ConfigurationClass中的Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars中去
    private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
                                Collection<SourceClass> importCandidates, boolean checkForCircularImports) {

        if (importCandidates.isEmpty()) {
            return;
        }

        if (checkForCircularImports && isChainedImportOnStack(configClass)) {
            this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
        } else {
            this.importStack.push(configClass);
            try {
                for (SourceClass candidate : importCandidates) {
                    if (candidate.isAssignable(ImportSelector.class)) {
                        // Candidate class is an ImportSelector -> delegate to it to determine imports
                        Class<?> candidateClass = candidate.loadClass();
                        ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
                        ParserStrategyUtils.invokeAwareMethods(
                                selector, this.environment, this.resourceLoader, this.registry);
                        if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
                            this.deferredImportSelectors.add(
                                    new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
                        } else {
                            String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                            Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
                            processImports(configClass, currentSourceClass, importSourceClasses, false);
                        }
                    } else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                        // Candidate class is an ImportBeanDefinitionRegistrar ->
                        // delegate to it to register additional bean definitions
                        Class<?> candidateClass = candidate.loadClass();
                        ImportBeanDefinitionRegistrar registrar =
                                BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
                        ParserStrategyUtils.invokeAwareMethods(
                                registrar, this.environment, this.resourceLoader, this.registry);
                        configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                    } else {
                        // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
                        // process it as an @Configuration class
                        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();
            }
        }
    }

這個(gè)方法大概的作用已經(jīng)在注釋中已經(jīng)寫明了,就不再重復(fù)了拙寡。

直到這里授滓,才把ConfigurationClassPostProcessor中的processConfigBeanDefinitions方法簡(jiǎn)單的過了一下。

但是這還沒有結(jié)束肆糕,processConfigBeanDefinitions是BeanDefinitionRegistryPostProcessor接口中的方法般堆,BeanDefinitionRegistryPostProcessor擴(kuò)展了BeanFactoryPostProcessor,還有postProcessBeanFactory方法沒有分析诚啃,這個(gè)方法是干嘛的淮摔,簡(jiǎn)單的來說,就是判斷配置類是Lite配置類始赎,還是Full配置類和橙,如果是配置類,就會(huì)被Cglib代理造垛,目的就是保證Bean的作用域魔招。關(guān)于這個(gè)方法實(shí)在是比較復(fù)雜,限于篇幅原因筋搏,這里就不再繼續(xù)了,有興趣的朋友可以到我的GitHub看下厕隧,里面有簡(jiǎn)單的分析(當(dāng)然其實(shí)還有很多東西無(wú)法在博客中體現(xiàn)奔脐,如果都貼出來的話,實(shí)在是太長(zhǎng)了吁讨,但是在GitHub上面都有注釋)髓迎。

我們來做一個(gè)總結(jié),ConfigurationClassPostProcessor中的processConfigBeanDefinitions方法十分重要建丧,主要是完成掃描排龄,最終注冊(cè)我們定義的Bean。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末翎朱,一起剝皮案震驚了整個(gè)濱河市橄维,隨后出現(xiàn)的幾起案子尺铣,更是在濱河造成了極大的恐慌,老刑警劉巖争舞,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凛忿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡竞川,警方通過查閱死者的電腦和手機(jī)店溢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來委乌,“玉大人床牧,你說我怎么就攤上這事≡饷常” “怎么了戈咳?”我有些...
    開封第一講書人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)革砸。 經(jīng)常有香客問我除秀,道長(zhǎng),這世上最難降的妖魔是什么算利? 我笑而不...
    開封第一講書人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任册踩,我火速辦了婚禮,結(jié)果婚禮上效拭,老公的妹妹穿的比我還像新娘暂吉。我一直安慰自己,他們只是感情好缎患,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開白布慕的。 她就那樣靜靜地躺著,像睡著了一般挤渔。 火紅的嫁衣襯著肌膚如雪肮街。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評(píng)論 1 312
  • 那天判导,我揣著相機(jī)與錄音嫉父,去河邊找鬼。 笑死眼刃,一個(gè)胖子當(dāng)著我的面吹牛绕辖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播擂红,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼仪际,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起树碱,我...
    開封第一講書人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤肯适,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后赴恨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疹娶,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年伦连,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了雨饺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡惑淳,死狀恐怖额港,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情歧焦,我是刑警寧澤移斩,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站绢馍,受9級(jí)特大地震影響向瓷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜舰涌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一猖任、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瓷耙,春花似錦朱躺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至鸡典,卻和暖如春源请,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背彻况。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工谁尸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人疗垛。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓症汹,卻偏偏與公主長(zhǎng)得像硫朦,于是被迫代替她去往敵國(guó)和親贷腕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容