spring-boot源碼分析之beanFactory · 捌

前言
今天,多余的話就不說(shuō)了,按照原計(jì)劃往下啃就行了,因?yàn)閮?nèi)容確實(shí)多,廢話多了怕分享不完
。
我們今天要分享四個(gè)方法:
invokeBeanFactoryPostProcessors:調(diào)用前面注冊(cè)的beanFactory后置處理器registerBeanPostProcessors:注冊(cè)bean后置處理器initMessageSource:初始化消息資源initApplicationEventMulticaster:初始化容器事件廣播(multicaster多播器)
下面我們就逐一展開(kāi)講下這四個(gè)方法。
refresh方法
invokeBeanFactoryPostProcessors
我們先看調(diào)用過(guò)程,在invokeBeanFactoryPostProcessors主要有兩部分操作。
一部分就是調(diào)用PostProcessorRegistrationDelegate類的靜態(tài)方法invokeBeanFactoryPostProcessors方法,這個(gè)方法內(nèi)容有點(diǎn)多,我們等下展開(kāi)講;
另一部分操作是往beanFactory中添加了LoadTimeWeaverAwareProcessor處理器,從名字可以看出這個(gè)處理器和切面編程有關(guān),同時(shí)包含了loadTime,說(shuō)明它和加載時(shí)間有關(guān)系,應(yīng)該是統(tǒng)計(jì)資源或者類的加載時(shí)間的的切面處理器,這里還往容器中set了一個(gè)臨時(shí)類加載器。

下面我們展開(kāi)看下靜態(tài)處理方法invokeBeanFactoryPostProcessors。下面是這個(gè)方法的完整代碼:

part1
先看part1的內(nèi)容。
在invokeBeanFactoryPostProcessors方法內(nèi)部,先循環(huán)beanFactoryPostProcessors,然后根據(jù)其類型,分別放進(jìn)beanFactory和beanDefinitonRegistry后置容器中,前一種和beanFactory相關(guān)的處理器,后一種是和這里的后置處理來(lái)源于容器,這里分類放置,是為了后期執(zhí)行不同的后置處理方法。
對(duì)于BeanDefinitionRegistryPostProcessor類型的后置處理器,除了往容器中添加之外,還會(huì)執(zhí)行postProcessBeanDefinitionRegistry方法,這個(gè)方法和我們昨天分享的postProcessBeanFactory方法很類似,方法的作用也大同小異,至少操作的對(duì)象不一樣,昨天的方法針對(duì)的是beanFactroy,今天的這個(gè)方法針對(duì)的是beanDefinitionRegisty。所以這個(gè)方法的作用就是在標(biāo)準(zhǔn)初始化之后(bean已加載未進(jìn)行實(shí)例化操作),修改bean的定義信息(在下次后置處理之前)。
part2~4
part2~4的大部分代碼都一樣,唯一的區(qū)別是if條件語(yǔ)句不一樣,part2匹配的是繼承了PriorityOrdered(優(yōu)先順序)的后置處理器;part3匹配的是繼承了Ordered,且不在processedBeans(未被添加過(guò),即不包括part2已經(jīng)處理的);part4匹配的是前兩類未處理的。匹配完之后,先進(jìn)行排序操作,然后再放進(jìn)registryProcessors中,最后進(jìn)行統(tǒng)一操作。這里還會(huì)調(diào)用invokeBeanDefinitionRegistryPostProcessors方法,當(dāng)然實(shí)際上調(diào)用的是BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,也就是我們part1說(shuō)的方法。
再下面就是根據(jù)bean的類型獲取beanFactory的postProcessor的名字,然后再根據(jù)postProcessor的名字拿出對(duì)應(yīng)的beanFactory后置處理,放進(jìn)不同的容器中,有順序的的需要先排個(gè)序,最后執(zhí)行調(diào)用beanFactory的postProcessBeanFactory,這個(gè)方法中基本上都是在進(jìn)行依賴注冊(cè)。
registerBeanPostProcessors
這個(gè)方法從名字來(lái)看,它應(yīng)該是注冊(cè)bean的后置處理器的,這里它調(diào)用的也是PostProcessorRegistrationDelegate靜態(tài)方法,不過(guò)它調(diào)用的是registerBeanPostProcessors,這個(gè)靜態(tài)方法內(nèi)容實(shí)現(xiàn)還挺多的,所以我們也需要展開(kāi)分析下。

下面我們就展開(kāi)這個(gè)方法講一下,這個(gè)方法我也把它分為四個(gè)部分,我們先看part 1。

part1
這部分就是往beanFactory中注入了一個(gè)bean的后置處理器,從名字看這個(gè)后置處理器應(yīng)該是一個(gè)后置處理器的檢查器,這個(gè)檢測(cè)器的其中一個(gè)參數(shù)是我們bean后置處理器數(shù)量+bean后置處理器名字集合的大小+1。
part2
這一部分循環(huán)遍歷了bean后置處理器的名字集合,然后根據(jù)名字獲取bean的后置處理器,對(duì)于優(yōu)先順序的后置處理器會(huì)直接放進(jìn)它的后置處理集合中,其他類型的后置處理器,會(huì)存放后置處理器名稱,便于part3和part4進(jìn)行循環(huán)操作。循環(huán)完之后,對(duì)有順序(優(yōu)先順序)的后置處理器要進(jìn)行排序操作,之后會(huì)把排序之后的后置處理器注冊(cè)到beanFactory中。
part3
這里的邏輯比part2差不多,而且比part2簡(jiǎn)單,所以就不再贅述。
part4
part4比part3多了一步注冊(cè),因?yàn)?code style="overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 100, 65);">part4要注冊(cè)兩種后置處理器,一種是內(nèi)部后置處理器,一種是無(wú)序的后置處理器。
最后還往beanFactory中注冊(cè)了一個(gè)bean后置處理,這個(gè)后置處理器的是應(yīng)用監(jiān)聽(tīng)器的探測(cè)器,應(yīng)該就是類似于監(jiān)控這樣的功能,它檢測(cè)的是應(yīng)用的監(jiān)聽(tīng)器。
initMessageSource
從名字看,這個(gè)方法進(jìn)行的是消息源的初始化,我記得我們前面好像提到過(guò),這個(gè)方法是和國(guó)際化有關(guān)的。這個(gè)方法其實(shí)就做了一件事,注冊(cè)messageSource,如果已經(jīng)被注冊(cè),則需要把注冊(cè)的值賦給容器的messageSource屬性

initApplicationEventMulticaster
初始化應(yīng)用事件的廣播器(多播)。與消息源初始化類似,這里就是簡(jiǎn)單的注冊(cè)和賦值,不存在就實(shí)例化然后注冊(cè),存在就直接賦值。

總結(jié)
今天這四個(gè)方法算是比較圓滿地分享完了,主要是前兩個(gè)方法確實(shí)有點(diǎn)長(zhǎng),分析完之后,才發(fā)現(xiàn)其實(shí)內(nèi)部也沒(méi)有太復(fù)雜的邏輯,甚至有些簡(jiǎn)單,但是我看了下字?jǐn)?shù),感覺(jué)問(wèn)題也并不簡(jiǎn)單,因?yàn)槟壳白謹(jǐn)?shù)已經(jīng)1500+了,如果照這個(gè)字?jǐn)?shù),明天四個(gè)方法很可能是分享完的,至少字?jǐn)?shù)是要大大超出今天這個(gè)量的,所以如果明天真的打臉我也認(rèn)了
好了,今天的四個(gè)方法就先分享到這里,勝利的曙光在望,加油呀~
- END -