1. 程式人生 > 其它 >Spring原始碼之bean的載入

Spring原始碼之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 例項

    1. 如果指定了 supplier 屬性:那麼不通過反射去例項化bean, 而是通過回撥 得到物件例項並返回。(面向函數語言程式設計提供回撥)

    2. 根據 BeanDefinition 判斷是否存在工廠方法,如果存在,呼叫工廠方法並返回。

    3. 解析建構函式,多個建構函式是,根據 getBean() 入參個數匹配建構函式,否則使用預設建構函式例項化 bean;

  • c. 依賴處理

    根據 bean 是否單例,以及 xml 配置決定是否提前暴露物件

                    單例  && 允許迴圈依賴   && bean 正在建立   === 是否允許提早曝光
    		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    				isSingletonCurrentlyInCreation(beanName));
    
  • e. 屬性填充

    1. 給 InstantiationAwareBeanPostProcessors.postProcessAfterInstantiation 最後一次機會,
      通過屬性注入改變 bean,它可以控制是否繼續對bean進行屬性填充。

    2. 根據型別(type)或者 名稱(name)注入依賴的bean;

    3. InstantiationAwareBeanPostProcessor.postProcessPropertyValues 對需要依賴檢查 的屬性,在屬性填充前,
      進行後處理器 處理;

    4. 將 PropertyValues [它快取解析到的當前載入bean依賴的所有bean] 注入到 BeanWrapper[bean的包裝器] 中。

  • f. 迴圈依賴檢查

    spring 解決依賴迴圈只對單例有效,prototype作用範圍的bean, spring沒有較好的解決辦法,只能丟擲異常。

  • g. 註冊disposableBean

    destory-method 定義的方法,物件銷燬時呼叫。