1. 程式人生 > >Spring的BeanFactoryPostProcessor和BeanPostProcessor區別

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實現類的兩個方法。