Spring的BeanFactoryPostProcessor和BeanPostProcessor區別
BeanFactoryPostProcessor:BeanFactory後置處理器,是對BeanDefinition物件進行修改。(BeanDefinition:儲存bean標籤的資訊,用來生成bean例項)
BeanPostProcessor:Bean後置處理器,是對生成的Bean物件進行修改。
一、BeanFactoryPostProcessor
該介面原始碼如下:
public interface BeanFactoryPostProcessor { //可以通過beanFactory獲取bean定義資訊 void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException; }
BeanFactoryPostProcessor介面是針對bean容器的,它的實現類可以在當前BeanFactory初始化(spring容器載入bean定義檔案)後,bean例項化之前修改bean的定義屬性,達到影響之後例項化bean的效果。
也就是說,Spring允許BeanFactoryPostProcessor在容器例項化任何其它bean之前讀取配置元資料,並可以根據需要進行修改,例如可以把bean的scope從singleton改為prototype,也可以把property的值給修改掉。可以同時配置多個BeanFactoryPostProcessor,並通過設定’order’屬性來控制各個BeanFactoryPostProcessor的執行次序。
spring中內建了一些BeanFactoryPostProcessor介面實現類,如下所示:
二、BeanPostProcessor
該方法的原始碼如下:
public interface BeanPostProcessor { //bean初始化之前呼叫 @Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } //bean初始化之後呼叫 @Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }
BeanPostProcessor能在spring容器例項化bean之後,在執行bean的初始化方法前後,新增一些自己的處理邏輯。初始化方法包括以下兩種:
1、實現InitializingBean介面的bean,對應方法為afterPropertiesSet
2、xml定義中,通過init-method設定的方法
BeanPostProcessor是BeanFactoryPostProcessor之後執行的。
spring中內建了一些BeanPostProcessor介面實現類,如下所示:
如果自定義了多個的BeanPostProcessor的實現類,通過實現Ordered介面,設定order屬性,可以按照順序執行實現類的方法。
三、例子
public class CustomBean implements InitializingBean {
private String desc;
private String remark;
public CustomBean() {
System.out.println("第二步:執行CustomBean類的無參建構函式");
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
System.out.println("第三步:呼叫setDesc方法");
this.desc = desc;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
System.out.println("第四步:呼叫setRemark方法");
this.remark = remark;
}
public void afterPropertiesSet() throws Exception {
System.out.println("第六步:呼叫afterPropertiesSet方法");
this.desc = "在初始化方法中修改之後的描述資訊";
}
public void initMethod() {
System.out.println("第七步:呼叫initMethod方法");
}
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("[描述:").append(desc);
builder.append(", 備註:").append(remark).append("]");
return builder.toString();
}
}
2、定義BeanFactoryPostProcessor
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("第一步:呼叫MyBeanFactoryPostProcessor的postProcessBeanFactory");
BeanDefinition bd = beanFactory.getBeanDefinition("customBean");
MutablePropertyValues pv = bd.getPropertyValues();
if (pv.contains("remark")) {
pv.addPropertyValue("remark", "在BeanFactoryPostProcessor中修改之後的備忘資訊");
}
}
}
3、定義BeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第五步:BeanPostProcessor,物件" + beanName + "呼叫初始化方法之前的資料: " + bean.toString());
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第八步:BeanPostProcessor,物件" + beanName + "呼叫初始化方法之後的資料:" + bean.toString());
return bean;
}
}
4、定義測試類
public class PostProcessorTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring/postprocessor.xml");
CustomBean bean = (CustomBean) context.getBean("customBean");
System.out.println("################ 例項化、初始化bean完成");
System.out.println("****************下面輸出結果");
System.out.println("描述:" + bean.getDesc());
System.out.println("備註:" + bean.getRemark());
}
}
執行結果如下:
第一步:呼叫MyBeanFactoryPostProcessor的postProcessBeanFactory
第二步:執行CustomBean類的無參建構函式
第三步:呼叫setDesc方法
第四步:呼叫setRemark方法
第五步:BeanPostProcessor,物件customBean呼叫初始化方法之前的資料: [描述:原始的描述資訊, 備註:在BeanFactoryPostProcessor中修改之後的備忘資訊]
第六步:呼叫afterPropertiesSet方法
第七步:呼叫initMethod方法
第八步:BeanPostProcessor,物件customBean呼叫初始化方法之後的資料:[描述:在初始化方法中修改之後的描述資訊, 備註:在BeanFactoryPostProcessor中修改之後的備忘資訊]
################ 例項化、初始化bean完成
****************下面輸出結果
描述:在初始化方法中修改之後的描述資訊
備註:在BeanFactoryPostProcessor中修改之後的備忘資訊
*************************************************************************
分析以上結果:在bean例項化之前,首先執行BeanFactoryPostProcessor實現類的方法,然後通過呼叫bean的無參建構函式例項化bean,並呼叫set方法注入屬性值。bean例項化後,執行初始化操作,呼叫兩個初始化方法(兩個初始化方法的順序:先執行afterPropertiesSet,再執行init-method)前後,執行了BeanPostProcessor實現類的兩個方法。