Spring Bean 的一生包括其從建立到消亡的整個過程:
例項建立 => 填充 => 初始化 => 使用 => 銷燬。
這裡需要注意的是,從 bean 例項的建立到可以使用之間還包括【填充】和【初始化】兩個步驟。
AbstractAutowireCapableBeanFactory::createBean:bean 建立核心方法,包含建立、填充 bean 例項及應用 post-processors 等邏輯。
一、例項建立
1、例項化前置處理
InstantiationAwareBeanPostProcessor 為 BeanPostProcessor 子介面,用以提供【建立例項】前後回撥處理。
如果有實現 InstantiationAwareBeanPostProcessor 介面,則應用此介面,返回結果如果不為 null,則直接返回作為 bean 例項。
2、doCreateBean
實際用於執行 bean 建立的方法,所有的建立、填充、初始化、註冊銷燬等邏輯都在此處處理。
BeanWrapper:Spring 底層 JavaBean 結構核心介面,提供了分析和管理 JavaBean 的相關操作。不直接使用,通常隱式的透過 BeanFactory 或者 DataBinder 來使用。此處執行邏輯即為使用 BeanWrapper 物件。
factoryBeanInstanceCache:儲存 FactoryBean name --> BeanWrapper 鍵值對映。執行例項建立伊始,會先從 factoryBeanInstanceCache 查詢獲取,存在則直接獲取(獲取後刪除)使用。
好吧,這裡有個問題,為什麼會有個 factoryBeanInstanceCache 快取?
源頭在於對單例 FactoryBean 型別操作,getSingletonFactoryBeanForTypeCheck。
建立 bean 例項 createBeanInstance:
優先順序順序:
-
透過 InstanceSupplier 建立(5.0以後)
-
透過工廠方法建立
-
建構函式建立
至此,bean 例項已建立完畢。
此處還有一個 post-processor 處理:MergedBeanDefinitionPostProcessor,用於 bean 定義修改(只針對 RootBeanDefinition:merge 了多個來源 BeanDefinition 的執行時檢視)。
3、單例例項提前暴露
為了解決單例迴圈依賴問題,提前將未完全建立好的單例例項快取起來。
這裡說的未完全建立好是指還不能正常使用。
earlySingletonExposure 條件:
-
單例:scope 為 “singleton” 或者 ”“。
-
允許自動處理迴圈依賴:allowCircularReferences 預設 true
-
單例 bean 處於建立中:DefaultSingletonBeanRegistry:singletonsCurrentlyInCreation 儲存所有處於建立中的 bean 名稱。
addSingletonFactory:
將 singletonFactory 新增到 singletonFactories 快取中,以備解決迴圈依賴使用。
singletonFactories 是什麼呢?
字面意思為單例工廠快取(bean name -> ObjectFactory ):即所謂的第三級快取,儲存目標 bean 所對應的 bean 工廠物件鍵值。
那 ObjectFactory 這個物件是怎麼獲取的呢?
SmartInstantiationAwareBeanPostProcessor::getEarlyBeanReference
SmartInstantiationAwareBeanPostProcessor 是 InstantiationAwareBeanPostProcessor 的擴充套件介面。
InstantiationAwareBeanPostProcessor 我們說過,是作用在建立例項前後。此處為建立例項後情景。
ObjectFactory 雖名為工廠,其實際為用以在 bean 建立早期,訪問相應 bean 的一個引用。
什麼是早期呢?
就是這會兒,剛建立完例項,還沒有進行相應的填充、初始化等後續操作。
那為什麼是暴露個引用,而不是直接給出目標物件呢?
因為目標 bean 可能還會經過其它 post-processors 處理。像 AbstractAutoProxyCreator::getEarlyBeanReference 中的代理邏輯處理。
二、填充
屬性填充,作用於 AbstractAutowireCapableBeanFactory::populateBean。
1、屬性填充前置處理
continueWithPropertyPopulation:是否繼續處理屬性填充判斷。
這裡的說明是在執行屬性填充前給予任何 InstantiationAwareBeanPostProcessors 一個機會來變更 bean 的狀態。
什麼意思呢?
就是 InstantiationAwareBeanPostProcessors 的 postProcessAfterInstantiation 處理,對目標 bean 做相應的變更。
做什麼變更呢?
這個節點在 Spring 自動注入操作之前,可以執行個性化的屬性注入。同時,方法返回值會賦予 continueWithPropertyPopulation,以決定是否執行後續的邏輯。
這裡有一個點需要注意:
如果當前 InstantiationAwareBeanPostProcessors::postProcessAfterInstantiation 返回 false,那麼 bean 屬性填充步驟則就此終止,不會再執行其它的 InstantiationAwareBeanPostProcessors 及後續的 Spring bean 屬性填充過程。
2、屬性填充
MutablePropertyValues
PropertyValues 介面的一個實現,提供對屬性的各種操作,同時提供相應的建構函式來支援深度複製及基於 Map 的構造。
自動注入方式:按順序 BY_NAME => BY_TYPE
BY_NAME
autowireByName 根據名稱填充
填充什麼呢?
unsatisfiedNonSimpleProperties。
什麼是 unsatisfiedNonSimpleProperties 呢?
-
可寫的:即擁有寫方法。
-
需要依賴檢查的:基於 ignoredDependencyTypes 屬性設定判斷。
-
非本身型別的。
-
非簡單型別屬性的:屬性本身型別及陣列元素型別為非簡單型別。包括(基本型別及其包裝型別,如 int、Integer 等)
注入:
首先根據屬性名稱判斷 bean 存在:
即是否包含在 bean 工廠及外部註冊單例 bean。
-
alias 的,會做相應的名稱轉換。
-
存在繼承關係的,會級聯向上查詢。
根據屬性名稱獲取 bean:AbstractBeanFactory::getBean。
屬性設定。
註冊 bean 依賴:dependentBeanMap beanName -> Set<BeanName>,即記錄 bean 及其依賴 bean 關係。
BY_TYPE
autowireByName 根據型別填充。
一個 BeanFactory 裡必須恰好只有一個匹配需要型別。
同樣,首先獲取需要填充的屬性:unsatisfiedNonSimpleProperties。
排除 Object 型別屬性,填充沒有意義。
處理依賴。
屬性設定
註冊 bean 依賴。
3、依賴檢查
依賴檢查分為兩部分:一個基於 InstantiationAwareBeanPostProcessor::postProcessPropertyValues 處理。一個基於 AbstractBeanDefinition::dependencyCheck 處理。
InstantiationAwareBeanPostProcessor:
對特定的屬性進行依賴檢查及處理;對特定屬性值進行替換,新增或者刪除。
如 RequiredAnnotationBeanPostProcessor、 AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、MockitoPostProcessor等。
dependencyCheck
檢查所有暴露的屬性是否都已賦值。
4、屬性賦值
將上述處理過的屬性值填充到 bean 例項。
三、初始化
應用工廠回撥,定義的初始化方法及post-processors。
1、Aware 處理
Aware 代表了各種各樣的資源,處理 Aware 即為將相應的資源新增到 bean 例項中。
如 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 等。
2、BeanPostProcessorsBeforeInitialization
顧名思義,這裡的 BeanPostProcessors 是初始化之前的處理。
如 AbstractAdvisingBeanPostProcessor 檢查。
3、執行初始化方法
a)實現了 InitializingBean 介面的 bean,執行相應的 afterPropertiesSet 方法。
b)定義了 initMethod 的,觸發相應的方法呼叫。
兩者是否可以同時存在呢?
可以,如果同時存在,但是初始化方法名稱不能為 afterPropertiesSet。執行順序為先 a 後 b。
4、BeanPostProcessorsAfterInitialization
同 2,此處為初始化之後的處理。
如 BeanValidationPostProcessor、ApplicationListenerDetector 等。
其實很多 PostProcessor 是既有 Before 處理邏輯,亦有 After 處理邏輯的,此處不再贅述。
四、disposable bean 註冊
bean 工廠維護了一個 disposable bean 列表(bean name --> disposable instance)。在工廠關閉銷燬時,同時銷燬相應的 bean 例項物件。
定義銷燬可以透過實現 DisposableBean 或者 AutoCloseable 介面或者自定義銷燬方法。
如果使用一個定義了相應銷燬方法的物件,又不想其執行銷燬方法時怎麼辦呢?
註解或者配置其銷燬方法為空,如:@Bean(destroyMethod = "")。
DestructionAwareBeanPostProcessor:例項銷燬前,使用者可以自定義執行特定的操作。如:ApplicationListenerDetector 移除相應的 Listener;ScheduledAnnotationBeanPostProcessor 移除定時任務等。