spring-boot源碼分析之beanFactory · 拾

前言
今天分享的refresh是的最后三個(gè)方法:
destroyBeanscancelRefreshresetCommonCaches
這三個(gè)方法中,有兩個(gè)位于catch語句塊,主要是用于refresh方法運(yùn)行異常時(shí),清除已經(jīng)構(gòu)建的bean和依賴的,另一個(gè)方法位于finally語句塊中,主要用于啟動(dòng)成功或失敗后重置各類緩存。
refresh最后的晚餐
finishRefresh補(bǔ)充
在開始今天的內(nèi)容之前,我們先對(duì)finishRefresh做一個(gè)簡單的補(bǔ)充。

finishRefresh方法內(nèi)部共調(diào)用了5個(gè)方法,第一個(gè)方法就是情況Resource的緩存,其內(nèi)部就是將DefaultResourceLoader的resourceCaches屬性置空,這個(gè)屬性是class和資源的map集合。


第二個(gè)方法是初始化生命周期處理器,其內(nèi)部就是往beanFactory中注冊(cè)一個(gè)名字為lifecycleProcessor的單例bean。并將這個(gè)bean賦值給當(dāng)前容器的lifecycleProcessor。

第三個(gè)方法就是獲取到第二個(gè)方法賦值的lifecycleProcessor,并執(zhí)行它的onRefresh方法。
從第二個(gè)方法那里可以看出來,生命周期處理器的類型為DefaultLifecycleProcessor,所以這里的的onRefresh方法內(nèi)部實(shí)現(xiàn)如下:

onRefresh方法內(nèi)部調(diào)用了 startBean方法,它的內(nèi)部實(shí)現(xiàn)如下:
根據(jù)bebug結(jié)果,最終還是會(huì)進(jìn)入forEach的if條件中,雖然autoStartOnly是true,但后面的條件是成立的,因此下面的for循環(huán)也會(huì)被執(zhí)行,最終會(huì) LifecycleGroup的start方法:

LifecycleGroup最終會(huì)調(diào)用bean的生命周期的start(就是我們昨天分析的createWebServer方法那里注冊(cè)的兩個(gè)生命周期bean)

后面兩個(gè)方法都很簡單,一個(gè)是推送事件,這里推送的是ContextRefreshedEvent事件;另一個(gè)方法是將當(dāng)前容器添加到LiveBeansView的applicationContexts容器中,也就不展開說明了。
剩余方法
今天要分析的是剩余的三個(gè)方法,這三個(gè)方法有兩個(gè)在catch中,也就是用了處理異常信息的,另一個(gè)個(gè)在finally中,也就是無論如何都會(huì)被執(zhí)行的,下面我們就詳細(xì)展開看一下。

destroyBeans
這個(gè)從名字就可以看出它的作用了,是的,就是銷毀已經(jīng)實(shí)例化完成的bean,也就是說如果refresh方法發(fā)生異常,會(huì)先銷毀所有的bean

在destroySingletons方法內(nèi)部,它首先調(diào)用了父類的destroySingletons方法,最終在父類的方法內(nèi)部調(diào)用destroySingletons以遞歸的方式銷毀bean和bean的依賴,具體流程如下:

cancelRefresh
發(fā)生異常后取消容器刷新操作,這里只是將容器的激活狀態(tài)改為false

resetCommonCaches
這個(gè)方法始終會(huì)被執(zhí)行,它的作用就是清理各種緩存以及classLoader,其中ReflectionUtils清理的是和反射相關(guān)的緩存,AnnotationUtils清理的是和注解相關(guān)的緩存,ResolvableType清理的是和解析類型相關(guān)的緩存,CachedIntrospectionResults.clearClassLoader清理的是類加載器的相關(guān)緩存。

至此,refresh方法算是徹底分享完了,run方法中剩余的方法,由于之前已經(jīng)分析過了,所以這里就不過多贅述了,后面就該花時(shí)間把最近一段時(shí)間的內(nèi)容好好梳理下,然后該補(bǔ)充的再補(bǔ)充下(比如上周五的內(nèi)容)。

總結(jié)
說實(shí)話我是沒想到剩余的三個(gè)方法這么簡單,總體內(nèi)容都沒有昨天finishRefresh的補(bǔ)充內(nèi)容多,不過也能想明白,畢竟今天內(nèi)容就是catch和finally語句塊的方法,也不會(huì)有太核心的內(nèi)容。
今天分享完畢后,剩余的工作就是查漏補(bǔ)缺和知識(shí)點(diǎn)梳理了,原本想著經(jīng)過梳理run方法會(huì)發(fā)現(xiàn)有集中初始化的代碼,但是截止到現(xiàn)在都沒找到,至少不像我之前手寫的web服務(wù)器那種,不過現(xiàn)在感覺似乎已經(jīng)對(duì)spring boot的bean的完整初始化過程有了一點(diǎn)點(diǎn)懵懂的認(rèn)知,我想等我梳理完最近分析的代碼,這一團(tuán)迷霧一定會(huì)被揭開……
好了,今天就先到這里吧,各位小伙伴,晚安喲!
- END -