ApplicationContext啟動之后會實例化所有的bean定義,這個特性在本書中已經多次提到。但ApplicationContext在實現的過程中依然遵循Spring容器實現流程的兩個階段,只不過它會在啟動階段的活動完成之后,緊接着調用注冊到該容器的所有bean定義的實例化方法getBean()。這就是為什么當你得到ApplicationContext類型的容器引用時,容器內所有對
象已經被全部實例化完成。不信你查一下類org.AbstractApplicationContext的refresh()方法。
下圖是bean生命周期圖
第一部分:Bean的聲明周期
1. Bean的實例化與BeanWrapper
容器在內部實現的時候,采用“策略模式(Strategy Pattern)”來決定采用何種方式初始化bean實例。通常,可以通過反射或者CGLIB動態字節碼生成來初始化相應的bean實例或者動態生成其子類。org.springframework.beans.factory.support.InstantiationStrategy定義是實例化策略的抽象接口,其直接子類SimpleInstantiationStrategy實現了簡單的對象實例化功能,可以通過反射來實例化對象實例,但不支持方法注入方式的對象實例化。CglibSubclassingInstantiation-Strategy繼承了SimpleInstantiationStrategy的以反射方式實例化對象的功能,並且通過CGLIB的動態字節碼生成功能,該策略實現類可以動態生成某個類的子類,進而滿足了方法注入所需的對象實例化需求。默認情況下,容器內部采用的是CglibSubclassingInstantiationStrategy。容器只要根據相應bean定義的BeanDefintion取得實例化信息,結合CglibSubclassingInstantiationStrategy以及不同的bean定義類型,就可以返回實例化完成的對象實例。但是,返回方式上有些“點綴”。不是直接返回構造完成的對象實例,而是以BeanWrapper對構造完成的對象實例進行包裹,返回相應的BeanWrapper實例
使用BeanWrapper對bean實例操作很方便,可以免去直接使用Java反射API(Java Reflection API)操作對象實例的煩瑣。來看一段代碼(見代碼清單4-49),之后我們就會更加清楚Spring容器內部是如何設置對象屬性的了!
2. 各色的Aware接口
3. BeanPostProcessor
BeanPostProcessor的概念容易與BeanFactoryPostProcessor的概念混淆。但只要記住Bean-PostProcessor是存在於對象實例化階段,而BeanFactoryPostProcessor則是存在於容器啟動階段,這兩個概念就比較容易區分了。
與BeanFactoryPostProcessor通常會處理容器內所有符合條件的BeanDefinition類似,Bean-PostProcessor會處理容器內所有符合條件的實例化后的對象實例。該接口聲明了兩個方法,分別在兩個不同的時機執行
通常比較常見的使用BeanPostProcessor的場景,是處理標記接口實現類,或者為當前對象提供
代理實現。在圖4-10的第三步中,ApplicationContext對應的那些Aware接口實際上就是通過Bean-
PostProcessor的方式進行處理的
4. InitializingBean和init-method
實現InitializingBean接口,或者在spring配置文件中bean定義中使用init-method
5. DisposableBean與destroy-method
實現DisposableBean接口,或者在spring配置文件中bean定義中使用destroy-method
保證jvm關閉前調用自定義銷毀邏輯
對於ApplicationContext容器來說。道理是一樣的。但AbstractApplicationContext為我們提供了registerShutdownHook()方法,該方法底層使用標准的Runtime類的addShutdownHook()方式來調用相應bean對象的銷毀邏輯,從而保證在Java虛擬機退出之前,這些singtleton類型的bean對象實例的自定義銷毀邏輯會被執行。當然AbstractApplicationContext注冊的shutdownHook不只是調用對象實例的自定義銷毀邏輯,也包括ApplicationContext相關的事件發布等,代碼清單4-58演示了該方法的使用。
第二部分:自定義BeanPostProcessor
(1) 標注需要進行解密的實現類
(2) 實現相應的BeanPostProcessor對符合條件的Bean實例進行處理
public class PasswordDecodePostProcessor implements BeanPostProcessor
(3) 將自定義的BeanPostProcessor注冊到容器
<beans> <bean id="passwordDecodePostProcessor" class="package.name.PasswordDecodePostProcessor"> <!--如果需要,注入必要的依賴--> </bean> 10 ... </beans>
大功告成!!!