1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        spring-boot源碼分析之BeanFactory · 壹

        共 5615字,需瀏覽 12分鐘

         ·

        2021-09-06 15:38


        前言

        今天原本是打算分析beanFactory的,但由于昨天我們有一部分內(nèi)容還沒有分享完,所以今天就先開個倒車,把昨天的內(nèi)容先講清楚了再說別的,因此今天的內(nèi)容主要就是對昨天分享內(nèi)容的的補(bǔ)充。

        當(dāng)然,昨天我們分享的內(nèi)容beanDefinitionNames也算是BeanFactory的核心屬性,所以也不能說完全沒有關(guān)系:

        而且從源碼中我們可以看出來,beanDefinitionNames、beanDefinitionMap這些屬性的初始化大小,這也算是在學(xué)習(xí)beanFactory的相關(guān)知識吧。

        BeanFactory

        beanDefinitionNames內(nèi)容補(bǔ)充

        正式開始之前,我們先把昨天遺留的問題解決了。昨天,我們分享了一張beanDefinitionNames初始化的時序圖,但是由于有一些內(nèi)容沒有梳理清楚,所以這里先做個補(bǔ)充。

        調(diào)用過程各方法作用

        SpringApplication這里就不做過多說明了,我們在前面最開始的時候就已經(jīng)分析過這個類的run方法,當(dāng)時也已經(jīng)介紹過這個類的這些方法,他們的主要作用就是為了初始化容器,在SpringApplication的最后一個refresh方法中,最后會調(diào)用AbstractApplicationContext自身的refresh方法,這里的AbstractApplicationContextApplicationContext的抽象實現(xiàn),它實現(xiàn)了ConfigurableApplicationContext接口(ConfigurableApplicationContext繼承了ApplicationContext),我們的AnnotationConfigReactiveWebServerApplicationContext(默認(rèn)容器)就是繼承自它,不過并不是直接繼承,它的父類繼承了AbstractApplicationContext,關(guān)于容器這塊的繼承關(guān)系,我們改天抽個時間,專門分析下。

        大部分繼承了AbstractApplicationContext的容器都沒有重寫refresh方法,就算重寫了這個方法,其內(nèi)部也是調(diào)用了父類的refresh方法:

        我們看下refresh的實現(xiàn)源碼:

         public void refresh() throws BeansException, IllegalStateException {
          synchronized (this.startupShutdownMonitor) {
           // Prepare this context for refreshing.
           prepareRefresh();

           // Tell the subclass to refresh the internal bean factory.
           ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

           // Prepare the bean factory for use in this context.
           prepareBeanFactory(beanFactory);

           try {
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);

            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            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();
           }
          }
         }

        refresh方法內(nèi)部,調(diào)用了很多其他方法,其中prepareRefresh的作用是為我們下面的刷新操作做準(zhǔn)備,其內(nèi)部主要是對配置的一些初始化操作:

        obtainFreshBeanFactory方法的作用是刷新beanFactory,主要是對beanFactory進(jìn)行一些初始化操作,如果beanFactory已經(jīng)存在,會將已有的beanFactory銷毀,然后重新創(chuàng)建,最后將beanFactory返回:

        prepareBeanFactory方法的作用是對BeanFactory進(jìn)行一些賦值和設(shè)置,為容器初始化操作做準(zhǔn)備:

        postProcessBeanFactory方法就是我們昨天提到的會進(jìn)行包掃描的那個方法,但由于basePackagesannotatedClasses都是空,所以其中的scan方法并不會被執(zhí)行。這個方法實際的作用是,后置處理BeanFactory

        invokeBeanFactoryPostProcessors方法的作用是,實例化并調(diào)用所有注冊的BeanFactory的后置處理器。我們昨天說的beanDefinitionNamesbeanDefinitionMap就是通過這個方法最終完成初始化的:

        registerBeanPostProcessors方法和它名字一樣,它的作用就是注冊bean的后置處理器:

        initMessageSource方法是進(jìn)行消息源初始化的,主要是對web應(yīng)用消息國際化提供支持的:

        initApplicationEventMulticaster,這個方法是初始化spring boot應(yīng)用時間廣播的,如果不指定的話,默認(rèn)情況下為我們指定的是SimpleApplicationEventMulticaster

        onRefresh,這個方法是提供給子類初始化其他特殊bean對象的,默認(rèn)實現(xiàn)為空,子類可根據(jù)需要重寫:

        registerListeners方法是用來注冊事件監(jiān)聽器的:

        finishBeanFactoryInitialization,完成beanFactory初始化,同時在方法內(nèi)部會實例化剩余的單例類(不包括懶加載部分):

        finishRefresh,完成刷新,主要進(jìn)行一些清理、刷新、事件推送等操作:

        總結(jié)

        經(jīng)過今天的補(bǔ)充之后,我相信各位小伙伴一定也對spring boot的啟動和初始化過程有了更深刻的認(rèn)識,因為我就是這樣的感受。相比于昨天分享完內(nèi)容的感受,今天我感覺整體來說要更好。一方面感覺spring boot啟動和初始化的流程更清晰了,而且由于最近這幾天一直在看spring boot的源碼,看的多了感覺就沒有那么難了,畢竟書讀百遍其意自現(xiàn),代碼也是大同小異;另一方面在梳理分析的過程中,讓我也能夠清晰地看到下一步要分享的內(nèi)容,明確后面的前進(jìn)方向,這也算是意外的收獲吧。

        - END -


        瀏覽 38
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            操人黄片 | 韩漫无遮韩漫免费网址肉 | 强伦理完整版 | 奇米成人AV | 国产精品大屁股白浆免费A片 | chinesewoman熟乱 | 激情五月av | 欧美肏屄片 | 女生性高潮视频 | 狠狠狠狠的青草 |