spring-boot原始碼分析之beanFactory · 肆
前言
昨天我們又分析了容器的建立過程,從容器的建立過程中,我們找到了beanFactory
例項化後最基本的初始化——註冊需要忽略的介面(ignoreDependencyInterface
)、註冊配置處理器(registerAnnotationConfigProcessors
),beanFactory
剩餘的初始化操作都在後面的方法中,今天我們先來看prepareContext
,雖然在prepareContext
前面還有一個getSpringFactoriesInstances
方法,但是這個方法並沒有和beanFactory
進行互動,所以就直接跳過了。
prepareContext
關於這個方法,我們前面已經分析過了,但基本上都是一帶而過,所以今天我們就沿著beanFactory
我們先來梳理下這個方法的執行流程:
-
設定容器環境(
context.setEnvironment
),這一步操作基本與beanFacotry
沒有關係,有的也是一些取值操作,並沒有往beanFactory
中註冊資料: -
容器後置處理(
postProcessApplicationContext
),這個方法內部主要有三步操作。第一步是往beanFactory
中註冊beanName
生成器,但由於預設情況下這個配置為空,所以並未進行註冊操作;第二步是設定容器的資源載入器,由於resourceLoader
是空,所以這裡也沒有設定;最後一步是註冊轉換服務,預設情況下會為我們註冊136
可以看到預設情況下為我們註冊的轉換器包括了
String
轉Date
這種常用的轉換,當然我們也可以定義自己的轉換器,這個我記下來,後面專門出一期demo
示例。 -
初始化操作(
applyInitializers
),這個方法我們昨天已經分析過了,這裡就不再贅述了,後面關於ApplicationContextInitializer
的初始化我也會專門做一期demo
分享的。 -
繫結容器初始化事件(
contextPrepared
),這個方法在容器建立並準備好之後,資源載入完成前執行,這一步和beanFactory
也沒有關係 -
列印
startupInfo
。下面那一段程式碼就是列印啟動日誌資訊, 預設情況下logStartupInfo
是true
,所以控制檯會輸出兩行日誌: -
獲取
beanFactory
(context.getBeanFactory()
),這個是為了方便後面註冊資料,因為緊接著就需要把springApplicationArguments
、springBootBanner
等註冊到beanFactory
中:最終
registerSingleton
方法會把他們註冊到singletonObjects
容器中,從名字我們就可以看出來,這是個存放單例物件的容器。 -
設定是否允許同名覆蓋(
setAllowBeanDefinitionOverriding
),預設情況下為true
(allowBeanDefinitionOverriding
屬性預設值)。如果為true
,後面的BeanDefinition
資料會將前面的覆蓋掉。但是預設啟動時,spring boot
會將它該為false
-
新增
beanFactory
懶載入後置處理器(addBeanFactoryPostProcessor
),由於預設情況下並未啟動懶載入,所以預設情況下懶載入後置處理器也不會被新增 -
獲取所有資源(
getAllSources
),預設情況下只包括當前spring boot
專案的主類,同時關聯了包括classLoader
、packages
等資料 -
將資源載入到容器中(
load
,官方文件給的解釋是bean
)。這個方雖然看起來其貌不揚,但是內部操作還是蠻多的。本來內容已經寫出來了,但是介於篇幅我決定把剩餘內容放到明天分享,當然也是因為load
方法確實也比較重要,其內部不僅包括了scanner
的初始化,而且包括了filter
的相關內容,這些都算是spring boot
的核心內容,所以還是要儘可能詳細些。
總結
原本是打算把prepareContext
的內容一次性分享完的,但是實際分享的時候,發現內容還是蠻多的,特別是load
方法,一個看起來小小的方法,沒想到它的內部初始化操作還挺複雜的。不過,經過今天的梳理之後,我感覺對prepareContext
認識要比之前清晰多了,而且在分析的過程中,還發現了兩個需要demo
實踐的內容,相關內容的flag
已經立起來了,後面就該填坑了,這也算是意外的收穫吧。
好了,今天就先到這裡吧!