天天看點

Spring Bean的生命周期小析(一)

session),第二個層面是執行個體化Bean時所經曆的一系列階段。我們将會對BeanFactory和ApplicationContext中的生命周期分别進行分析(BeanFactory和ApplicationContex的一個大的差別是:BeanFactory在初始化容器時,并未執行個體化Bean,直到第一次通路某個Bean時才執行個體目标Bean;而ApplicationContext則在初始化應用上下文時就執行個體化所有單執行個體的Bean。)本篇文章先說BeanFactory的生命周期。

Bean的生命周期所經曆的階段比較多,是以先奉上一個圖形化的生命周期的過程。

Spring Bean的生命周期小析(一)

在上面這個圖中我們需要注意這幾個類:InstantiationAwareBeanPostProcessor (或InstantiationAwareBeanPostProcessorAdapter)、BeanNameAware、BeanFactoryAware 、BeanPostProcessor 、InitializingBean、DisposableBean。

下面我們詳細的來說一下Bean生命周期的過程:

1、當調用者通過getBean(beanName)向容器請求某一個Bean時,如果容器注冊了org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口,在執行個體化Bean之前,将調用接口的postProcessBeforeInstantiation()方法;

2、根據配置情況調用Bean構造函數或工廠方法執行個體化Bean;

3、如果容器注冊了org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口,在執行個體化Bean之後,調用該接口的postProcessAfterInstantiation()方法,可在這裡對已經執行個體化的對象進行一些操作;

4、如果Bean配置了屬性資訊,容器在這一步着手将配置值設定到Bean對于的屬性中,不過在設定每個屬性之前将先調用org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues()方法(如果注冊了這個接口的話);

5、調用Bean的屬性設定方法設定屬性值;

6、如果Bean實作了org.springframework.beans.factory.BeanNameAware接口,将調用setBeanName接口方法,将配置檔案中該Bean對應的名稱設定到Bean中;

7、如果Bean實作了org.springframework.beans.factory.BeanFactoryAware接口,将調用setBeanFactory()接口方法,将BeanFactory容器執行個體設定到Bean中;

8、如果BeanFactory裝配了org.springframework.beans.factory.config.BeanPostProcessor後處理器,将調用BeanPostProcessor的postProcessBeforeInitialization(Object bean,String beanName)接口方法對Bean進行加工操作,其中入參bean是目前正在處理的Bean,而beanName是目前Bean的配置名,傳回的對象為加工處理後的Bean。使用者可以使用該方法對某些Bean進行特殊的處理,甚至改變Bean的行為,BeanPostProcessor在Spring架構中占有重要的地位,為容器提供對Bean進行後續加工處理的切入點,Spring容器所提供的各種“神奇功能”(如果AOP、動态代理等)都通過BeanPostProcessor實施;

9、如果Bean實作了org.springframework.beans.factory.InitializingBean接口,将調用afterPropertiesSet()方法;

10、如果在<bean>通過init-method屬性定義了初始化方法,将執行這個方法;

11、BeanPostProcessor後處理器定義了兩個方法:一個是postProcessBeforeInitialization()方法(在第8步調用);另一個是postProcessAfterInitialization(Object bean,String beanName)方法,這個方法在此時調用,容器再次獲得對Bean進行加工處理的機會;

12、如果在<bean>中指定Bean的作用範圍為scope=“prototype”,将Bean傳回給調用者,調用者負責Bean後續生命周期的管理,Spring不再管理這個Bean的生命周期。如果作用範圍設定為scope=“singleton”,則将Bean放入到Spring IoC容器的緩存池中,并将Bean的應用傳回給調用者,Spring繼續對這些Bean進行後續的生命管理。

13、對于scope=“singleton”的Bean,當容器關閉時,将觸發Spring對Bean的後續生命周期的管理工作,首先如果Bean實作了DisposableBean接口,将調用接口的destroy()方法,可以在此編寫釋放資源、記錄日志等操作;

14、對于scope=“singleton”的Bean,如果通過<bean>的destory-method屬性指定了Bean的銷毀方法,Spring将執行Bean的這個方法,完成Bean資源的釋放等操作。

上面一系列的文字看的我們眼花缭亂,我們來總結一下Bean的生命周期。Bean的生命周期大概分為一下三類:

Bean自身的方法:如調用Bean構造函數執行個體化Bean,調用settter設定Bean的屬性值以及通過<bean>的init-method和destory-method所指定的方法;

Bean級生命周期接口方法:像BeanNameAware、BeanFactoryAware、InitalizingBean和DisposableBean,這些接口方法由Bean類直接實作;

容器級生命周期接口方法:像InstantiationAwareBeanPostProcessor(或InstantiationAwareBeanPostProcessorAdapter)和BeanPostProcessor這兩個接口,一般稱他們的實作類為後處理器。後處理器接口一般不由Bean自身實作,它們獨立于Bean,實作類似容器附加裝置的形式注冊到Spring容器中并通過接口反射為Spring容器預先識别。當Spring容器建立任何Bean的時候,這些後處理器都會發生作用,是以這些後處理的影響是全局性的。如果有多個容器級的接口的實作的話,可以通過org.springframework.core.annotation.Order注解或者org.springframework.core.Ordered接口來指定執行的順序。

下面讓我們寫一個例子來測試一下Bean的生命周期的過程:

InstantiationAwareBeanPostProcessor接口是BeanPostProcessor接口的子接口,在Spring1.2中定義的,在Spring2.0中為其提供了一個擴充卡類org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter,一般情況下,我們可以友善的擴充該擴充卡覆寫感興趣的方法以定義實作類。所在我們在這裡也是繼承的InstantiationAwareBeanPostProcessorAdapter。

注意:我們這裡為BeanLifeCycleLearn01中設定的屬性值為zhangsan

Spring Bean的生命周期小析(一)

從上面的輸出結果我們可以看出,輸出的結果和我們在上面畫的生命周期的圖的過程是一樣的。如果我們将我們的作用于改為prototype的話,輸出結果是這樣的:

Spring Bean的生命周期小析(一)

總結:

通過實作Spring的Bean級生命周期接口對Bean進行一些額外的控制,讓Bean具有了更細緻的生命周期階段,但是這也帶來了一個問題,它們和代碼的耦合度比較高。關于Bean級的生命周期接口中的InitializingBean和DisposableBean,我們通常建議使用<bean>的init-method和destory-method這兩個屬性為Bean指定初始化和銷毀的方法。在Spring2.1中增加了一個InitDestroyAnnotationBeanPostProcessor這個類,我們可以使用@PostConstruct和@PreDestroy注解來指定初始化和銷毀的方法。對于容器級的生命周期接口BeanPostProcessor,它不要求Bean去繼承它,可以像插件一樣注冊到Spring容器中,為容器提供額外的功能。

參考:

Spring 3.x 企業應用開發實戰   陳雄華 林開雄著。