?
????? Spring不僅提供了基本的IOC功能,借助于BeanFactory以及其它組件,我們還可以使用其它一些更高級的功能。但是需要注意的是,使用這些高級功能,將不可避免的使得我們的工程依賴于Spring。這些高級功能大致包括:管理bean的生命周期,讓bean感知Spring(Spring aware),使用方法注入,使用FactoryBean,使用PropertyEditor以及了解Spring的ApplicationContext
??????有時候,我們需要在bean的生命周期中的某些階段做一些相應的操作(類似于Servlet和EJB),像其它IOC容器一樣,Spring也提供了管理bean生命周期的功能。兩個主要的階段是:
post-initialization(bean初始化之后)和pre-destruction(bean銷毀之前).
????? post-initialization是指在Spring完成了bean的所有依賴注入以及相應的檢測之后,
????? pre-destruction是指在Spring銷毀bean之前。
????? post-initialization和pre-destruction只能應用于sigleton模式的bean,因為非sigleton的bean的生命周期并不由Spring控制(它們是由JVM控制的)。
????? Spring提供了兩種機制來實現bean生命周期的管理:基于接口的和基于指定方法的。
????? 使用基于接口的機制,我們需要實現Spring的相關接口,然后,Spring會使用回調機制在指定的階段調用接口中定義的方法,從而實現bean生命周期的管理。而使用基于指定方法的機制,我們需要在BeanFactory的配置中指定相應的方法名稱,Spring會使用Java的反射機制在指定的階段調用我們指定的方法,從而實現bean生命周期的管理。
????? 選擇哪種機制取決于我們的工程的需要。基于接口的機制要求我們實現Spring的接口,這會帶來對Spring的依賴,但是當我們定義了很多相同類型的bean時,使用基于接口的機制可以免去我們為每個bean定義指定相應方法的麻煩。基于指定方法的機制則可以讓我們避免對Spring的依賴,這在當我們使用第三方的類庫(因此,我們無法修改其代碼來實現Spring的接口)時是非常有用的。
????? 以post-initialization為例:
????? 使用基于接口的機制,我們需要實現Spring的InitializingBean接口的afterPropertiesSet方法
????? public class SimpleBeanWithInterface implements InitializingBean {
????????? ...
????????? public void afterPropertiesSet() throws Exception {
????????????? ...
??????? ? }
????????? ...
????? }
????? <beans>
???????? <bean id="simpleBean1"
???????? class="com.apress.prospring.ch5.lifecycle.SimpleBeanWithInterface">
???????????? ...
???????? </bean>
????? </beans>
????? 使用基于指定方法的機制,我們只需在BeanFactory的配置中指定相應的方法名稱
????? <beans>
????????? <bean id="simpleBean1"
????????? class="com.apress.prospring.ch5.lifecycle.SimpleBean"
????????? init-method="init">
????????????? ...
??????????</bean>
????? </beans>
????? SimpleBean中包含對應的init方法
????? public class SimpleBean {
????????? ...
????????? public void init() {
????????????? ...
????????? }
????????? ...
????? }
????? 需要注意的是,init方法必須不包含任何參數,盡管我們可以為init方法指定任意的返回值,但Spring會忽略它,因此最好的做法是在init方法中拋出異常來表明初始化失敗了。
????? 我們也可以同時使用這兩種機制,這時,Spring會先調用InitializingBean接口的afterPropertiesSet方法,再調用我們自己指定的init方法。
????? 相對的,pre-destruction使用DisposableBean接口的destroy方法和bean標簽的destroy-method屬性
????? 相對于依賴查找(Dependency Lookup),依賴注入(Dependency Injection)最大的賣點就是容器的無關性,但是有時候,我們確實需要和容器進行一些交互,例如訪問BeanFactory或者是獲得bean的名稱等。
??????為了獲得bean的名稱,我們需要實現Spring的BeanNameAware接口,BeanNameAware只有一個方法,void setBeanName(String name),只要我們的bean實現了BeanNameAware接口,Spring就會在bean配置結束,其它生命周期相關的回調函數(initialization或者 destroy)調用之前,回調該方法置入bean的名稱。
????? 類似的,為了訪問beanFactory,我們需要實現Spring的BeanFactoryAware接口的
void setBeanFactory(BeanFactory factory)方法。