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 · 伍

        共 2811字,需瀏覽 6分鐘

         ·

        2021-09-12 22:01

        前言

        原本是打算昨天把prepareContext方法梳理完,今天開(kāi)始啃硬骨頭——refresh方法的,結(jié)果大家昨天就知道了:由于篇幅的問(wèn)題,剩余內(nèi)容放在今天分享了。

        然后今天的想法是除了昨天需要補(bǔ)充的內(nèi)容外,看能不能把refresh的內(nèi)容也分享一部分,畢竟是硬骨頭,然而現(xiàn)實(shí)情況是,在我把昨天需要補(bǔ)充的內(nèi)容梳理之后,發(fā)現(xiàn)剩余的內(nèi)容還不少,所以就只能先不開(kāi)始新的內(nèi)容了,等prepareContext方法徹底剖析完畢之后我們?cè)倏杏补穷^。

        下面就讓我們看下prepareContext的剩余內(nèi)容吧!

        prepareContext補(bǔ)充

        下面這些內(nèi)容原本是昨天要一起分享的,但是由于內(nèi)容比較多,而且昨天時(shí)間有點(diǎn)晚了,所以就沒(méi)來(lái)得及分享,下面我們就先來(lái)做一些簡(jiǎn)單的補(bǔ)充說(shuō)明。

        創(chuàng)建BeanDefinitionLoader

        首先是創(chuàng)建bean的定義加載器,創(chuàng)建beanDefiniton加載器的時(shí)候,首先是一個(gè)賦值操作,然后創(chuàng)建了AnnotatedBeanDefinitionReader,它的創(chuàng)建就稍微有點(diǎn)復(fù)雜。

        實(shí)例化ConditionEvaluator

        創(chuàng)建AnnotatedBeanDefinitionReader的時(shí)候要先創(chuàng)建ConditionEvaluator,而ConditionEvaluator實(shí)例化的時(shí)候又需要先實(shí)例化ConditionContextImpl,這里的ConditionEvaluatorConditionContextImplspring boot引入的新特性,主要用于條件配置,我們可以通過(guò)@Conditional注解使用這一特性,后面專門(mén)來(lái)分析吧(又發(fā)現(xiàn)新大陸了……)。

        最后一步都是賦值操作,就沒(méi)啥好講的了。

        另外,在load方法中調(diào)用了另一個(gè)方法registerAnnotationConfigProcessors。就說(shuō)這方法看著眼熟,原來(lái)我們昨天分析beanDefinitionMap初始化的時(shí)候,已經(jīng)研究過(guò)了。 

        這里注冊(cè)完成后beanDefinitionMap會(huì)多出5個(gè)元素。 

        下面兩個(gè)Reader的初始化就不再詳細(xì)分析了,基本上都是簡(jiǎn)單的實(shí)例化和賦值操作: 

        實(shí)例化scanner

        后面兩個(gè)操作有必要講一下,首先實(shí)例化了scanner,在實(shí)例化過(guò)程中,注冊(cè)了三個(gè)注解類型過(guò)濾器(AnnotationTypeFilter

        事實(shí)上,javax.inject.Named,并沒(méi)有被注冊(cè)成功,因?yàn)楫?dāng)前class并不存在,關(guān)于這一點(diǎn),下面的截圖可以很清楚地說(shuō)明,因?yàn)樵谧?cè)JSR-330class時(shí)候報(bào)了java.lang.ClassNotFoundException異常,所以最終的結(jié)果就是@Component@ManagedBean這兩種注解類型攔截器被成功注入,我們通過(guò)includeFilters的大小也可以看出這一點(diǎn)。

        注冊(cè)排除過(guò)濾器

        排除過(guò)濾器(excludeFilters)就是過(guò)濾不需要被掃描的資源。所以這一步的操作就比較簡(jiǎn)單了,就是往scanner的 排除過(guò)濾器(excludeFilters)中增加了一個(gè)ClassExcludeFilter,傳入的是sources,目前sources只有我們spring boot項(xiàng)目的主類。

        這里需要注意的是,excludeFilters本身是個(gè)List,所以這里add的時(shí)候其實(shí)是把新的排除注冊(cè)器放在excludeFilters的最前面。

        設(shè)置loader屬性

        下面就是這只loader的屬性,包括beanNameGenneratorresourceLoaderenvironment。但是由于這些參數(shù)都是空的,所以默認(rèn)情況下這些設(shè)置方法并不會(huì)被執(zhí)行:

        loader加載資源

        下面是load方法最核心的執(zhí)行流程,核心部分就是注冊(cè)Bean

        由于一張截圖無(wú)法完整體現(xiàn)registerBean的流程,所以我分成了兩張截圖,這里最核心的就是doRegisterBean方法,這個(gè)方法內(nèi)部會(huì)構(gòu)建當(dāng)前classBeanDefinition。其中AnnotatedGenericBeanDefinition是根據(jù)注解信息生成的beandefinition信息,包括beanClass、AnnotationMetadata(注解元數(shù)據(jù))、scope(范圍)等,總之就是凡是通過(guò)注解方式配置的類,都是通過(guò)AnnotatedGenericBeanDefinition來(lái)構(gòu)建它的definition信息的,它本身也就是為了支持注解元數(shù)據(jù)而生的。

        上面這些操作執(zhí)行完畢后會(huì)往beanFactorybeanDefinitionMapbeanDefinitionNames分別保存beanClassbeanNamebeanDefinition信息

        執(zhí)行事件監(jiān)聽(tīng)

        這里調(diào)用的是監(jiān)聽(tīng)器容器的contextLoaded方法,其方法內(nèi)部本質(zhì)上是觸發(fā)對(duì)應(yīng)的事件,從方法名上我們可以看出來(lái)這個(gè)方法其實(shí)發(fā)的就是容器已經(jīng)加載完成的事件。下面是Logger

        debug過(guò)程中,我發(fā)現(xiàn)這里觸發(fā)的時(shí)間類型是ApplicationPeparedEvent事件,這里的事件類別挺多的,不同的監(jiān)聽(tīng)器會(huì)執(zhí)行各自的onApplicationEvent方法,上面的流程中我們就是以LoggingApplicationListener為例,剖析其執(zhí)行流程的

        對(duì)于LoggingApplicationListener總共會(huì)處理5種事件,這里處理的是ApplicationPreparedEvent事件,也就是我們前面看到的類型

        在當(dāng)前事件類型下,LoggingApplicationListeneronApplicationEvent方法會(huì)往容器中注冊(cè)兩個(gè)單例實(shí)例,中間的logFile為空,所以并未成功注入。

        總結(jié)

        好了,到今天我們算是把prepareContext方法的內(nèi)容梳理完了,整體來(lái)看還算清晰。

        說(shuō)實(shí)話,我是沒(méi)想到一小塊補(bǔ)充內(nèi)容能有這么多,但事實(shí)確實(shí)如此,這也從側(cè)面說(shuō)明了spring boot本身確實(shí)比較復(fù)雜,任何一小行代碼,其內(nèi)部可能都潛藏著核心的實(shí)現(xiàn)代碼。我數(shù)了一下,不算括號(hào)和if語(yǔ)句,只有17行,但是就這短短的17行代碼,我用了近三千字還沒(méi)有說(shuō)的特別清楚,我自己都不敢想象,不過(guò)好的一點(diǎn)是,雖然中間磕磕絆絆,但也算是啃下來(lái)了,不過(guò)更硬的骨頭還在后頭——refresh方法才是重頭戲,還是不能松懈呀~

        最后,我想說(shuō)的是,任何一小行代碼很有可能就是解開(kāi)你心中困惑的鑰匙,所以不論是坑,還是意外收獲,更多時(shí)候都需要我們自己親自蹚~

        - END -


        瀏覽 39
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        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>
            亚洲女人天堂网 | 五月天伊人网 | 公共场合高潮(h)小说 | www18禁 | 久久久福利视频 | 四虎国产精品区 | 林熙蕾胸被揉到高潮后不让我吃奶 | 日本乱伦性爱 | 婷婷五月天激情综合网 | 大香蕉伊在线观看视频 |