Spring系列六:Spring BeanPostProcessor
人如風後入江雲,情似雨餘黏地絮。
概述
bean
後處理器允許自定義修改spring
bean factory
建立的新bean
例項。如果你想在Spring
容器完成例項化、配置和初始化bean
之後實現一些定製邏輯,我們可以插入一個或多個BeanPostProcessor
實現。
如果有多個BeanPostProcessor
例項,我們可以通過設定order
屬性或實現Ordered
介面來控制執行順序。
Spring BeanPostProcessor
BeanPostProcessor
介面由兩個回撥方法組成,即postprocessbeforeinitialize()
和postprocessafterinitialize()
對於由容器建立的每個bean
例項,後處理器都會在呼叫容器初始化方法之前以及在任何bean初始化回撥之後都從容器獲得回撥。
bean
後處理器通常檢查回撥介面,或者使用代理包裝bean
。例如一些Spring AOP
基礎結構類(例如AbstractAdvisingBeanPostProcessor
)實現了bean
後處理器,提供代理包裝邏輯。
如何建立BeanPostProcessor
spring
中建立一個bean
後處理器:
- 實現
BeanPostProcessor
介面。 - 實現回撥方法。
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class CustomBeanPostProcessor implements BeanPostProcessor
{
public Object postProcessBeforeInitialization(Object bean,String beanName) throws BeansException
{
System.out.println("Called postProcessBeforeInitialization() for :" + beanName);
return bean;
}
public Object postProcessAfterInitialization(Object bean,String beanName) throws BeansException
{
System.out.println("Called postProcessAfterInitialization() for :" + beanName);
return bean;
}
}
複製程式碼
如何註冊BeanPostProcessor
ApplicationContext
自動檢測實現BeanPostProcessor
介面的配置元資料中定義的所有bean
。它將這些bean
註冊為後處理器,以便以後在建立bean
時呼叫它們
然後Spring
將在呼叫初始化回撥方法之前和之後將每個bean
例項傳遞給這兩個方法,在這兩個方法中,你可以按自己喜歡的方式處理bean
例項。
<beans>
<bean id="customBeanPostProcessor"
class="com.howtodoinjava.demo.processors.CustomBeanPostProcessor" />
</beans>
複製程式碼
BeanPostProcessor
被呼叫方法時
通常,spring
的DI
容器會執行以下操作來建立一個bean
:
- 通過建構函式或工廠方法重新建立
bean
例項 - 設定屬性值值和對其它
bean
的引用 - 呼叫所有
*Aware
介面中定義的setter
方法 - 將
bean
例項傳遞給每個bean
後處理器的postProcessBeforeInitialization()
方法 - 呼叫初始化回撥方法
- 將
Bean
例項傳遞到每個Bean
後處理器的postProcessAfterInitialization()
方法 - 這個
bean
已經可以被使用了 - 當容器關閉時,呼叫銷燬回撥方法
Spring
BeanPostProcessor
示例
為了展示示例用法,我使用了EmployeeDAOImpl
類,如下所示:
public class EmployeeDAOImpl implements EmployeeDAO
{
public EmployeeDTO createNewEmployee()
{
EmployeeDTO e = new EmployeeDTO();
e.setId(1);
e.setFirstName("Lokesh");
e.setLastName("Gupta");
return e;
}
public void initBean() {
System.out.println("Init Bean for : EmployeeDAOImpl");
}
public void destroyBean() {
System.out.println("Init Bean for : EmployeeDAOImpl");
}
}
複製程式碼
該bean
及其後處理器的配置如下:
<bean id="customBeanPostProcessor" class="com.howtodoinjava.demo.processors.CustomBeanPostProcessor" />
<bean id="dao" class="com.howtodoinjava.demo.dao.EmployeeDAOImpl" init-method="initBean" destroy-method="destroyBean"/>
複製程式碼
現在,啟動DI
容器並檢視輸出:
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
複製程式碼
輸出:
Called postProcessBeforeInitialization() for : dao
Init Bean for : EmployeeDAOImpl
Called postProcessAfterInitialization() for : dao
複製程式碼
很顯然,在初始化方法之前和之後呼叫了BeanPostProcessor方法。