Spring原始碼之bean的載入
- 1. FactoryBean 的使用
- 2. 快取中獲取單例 bean;
- 3. 從 bean 例項獲取物件,
- 4. 獲取單例 bean (從快取載入失敗);
- 5. 建立 bean (createBean)
- 6. 迴圈依賴
- 7. 建立 bean
本文程式碼入口:
\spring-framework-5.0.x\spring-beans\src\main\java\org\springframework\beans\factory\support\AbstractBeanFactory.getBean(String name);
* ***PS * 本文僅供學習,如有謬誤,感謝指正。***
1. FactoryBean 的使用
bean 比較複雜的時候,需要大量配置資訊。
可以通過工廠,定製 bean 的例項化,從而擺脫大量配置資訊,靈活性提高。如: class="xx.xxx.FactoryBeanImpl",呼叫 getBean(beanName),將返回 FactoryBeanImpl.getObject()。
2. 快取中獲取單例 bean;
單例 bean 只會被建立一次,優先從快取中獲取,獲取失敗,再進入載入流程。(確保容器中只有一個 bean)
3. 從 bean 例項獲取物件,
檢查 bean 是否為 FactoryBean 型別;若是,FactoryBean呼叫其 getObject方法,否則返回解析到的 bean。
4. 獲取單例 bean (從快取載入失敗);
從 ObjectFactory 獲取 bean (回撥它的 getObject() 方法,再去呼叫 creatBean()方法,建立 bean 由子類:spring-beans\src\main\java\org\springframework\beans\factory\support\AbstractAutowireCapableBeanFactory.java提供實現)
java sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException{ // 準備完成後回撥 由子類 AbstractAutowireCapableBeanFactory 實現方法 return createBean(beanName, mbd, args); } }
5. 建立 bean (createBean)
- a.處理 overrride 屬性 lookup-method (策略模式應用,bean替換??) replace-method (動態替換方法的實現)
- b.例項化前 <後處理器>,
對 BeanDefinition 的屬性做前置化處理,提高拓展能力;
提供了一個短路邏輯,如果該 <後處理器> 返回值不為空,則直接呼叫 例項化後 的 <後處理器>,
並把 通用的 bean 建立環節短路掉。 - c.例項化後 <後處理器>
6. 迴圈依賴
- a. 構造器迴圈依賴 無法解決
- b. setter 注入迴圈依賴 (bean 未建立完畢就將其 ObjectFactory 暴露,當別的bean 依賴他時,
即使該 bean 尚未完成載入,也可以從快取中,獲取到該提前暴露的 ObjectFactory ) - c. prototype(原型模式)範圍的依賴處理
該模式 bean spring 容器不會進行快取,因此無法提前暴露一個 bean
7. 建立 bean
-
a. 單例 bean 先清除快取,確保 spring 容器中只有一個bean
-
b. 獲取 bean 例項
-
如果指定了 supplier 屬性:那麼不通過反射去例項化bean, 而是通過回撥 得到物件例項並返回。(面向函數語言程式設計提供回撥)
-
根據 BeanDefinition 判斷是否存在工廠方法,如果存在,呼叫工廠方法並返回。
-
解析建構函式,多個建構函式是,根據 getBean() 入參個數匹配建構函式,否則使用預設建構函式例項化 bean;
-
-
c. 依賴處理
根據 bean 是否單例,以及 xml 配置決定是否提前暴露物件
單例 && 允許迴圈依賴 && bean 正在建立 === 是否允許提早曝光 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
-
e. 屬性填充
-
給 InstantiationAwareBeanPostProcessors.postProcessAfterInstantiation 最後一次機會,
通過屬性注入改變 bean,它可以控制是否繼續對bean進行屬性填充。 -
根據型別(type)或者 名稱(name)注入依賴的bean;
-
InstantiationAwareBeanPostProcessor.postProcessPropertyValues 對需要依賴檢查 的屬性,在屬性填充前,
進行後處理器 處理; -
將 PropertyValues [它快取解析到的當前載入bean依賴的所有bean] 注入到 BeanWrapper[bean的包裝器] 中。
-
-
f. 迴圈依賴檢查
spring 解決依賴迴圈只對單例有效,prototype作用範圍的bean, spring沒有較好的解決辦法,只能丟擲異常。
-
g. 註冊disposableBean
destory-method 定義的方法,物件銷燬時呼叫。