10--Spring BeanPostProcessor和BeanFactoryPostProcessor的區(qū)別

  • BeanPostProcessor接口:后置bean處理器,允許自定義修改新的bean實例甸昏,應(yīng)用程序上下文可以在其bean定義中自動檢測BeanPostProcessor類型的bean撇贺,并將它們應(yīng)用于隨后創(chuàng)建的任何bean谦疾。(例如:配置文件中注冊了一個自定義BeanPostProcessor類型的bean纷闺,一個User類型的bean刨秆,應(yīng)用程序上下文會在創(chuàng)建User實例之后對User應(yīng)用BeanPostProcessor)凳谦。
  • BeanFactoryPostProcessor接口:后置工廠處理器,允許自定義修改應(yīng)用程序上下文的bean定義衡未,調(diào)整bean屬性值尸执。應(yīng)用程序上下文可以在其bean定義中自動檢測BeanFactoryPostProcessor,并在創(chuàng)建任何非BeanFactoryPostProcessor類型bean之前應(yīng)用它們(例如:配置文件中注冊了一個自定義BeanFactoryPostProcessor類型的bean缓醋,一個User類型的bean如失,應(yīng)用程序上下文會在創(chuàng)建User實例之前對User應(yīng)用BeanFactoryPostProcessor)。

對比 BeanFactoryPostProcessor BeanPostProcessor
回調(diào)時間 Bean實例化完成之前 Bean實例化完成之后
是否可修改bean定義信息
是否可修改bean實例信息
是否支持排序接口
方法級別 ApplicationContext級別 ApplicationContext級別
實現(xiàn)方式 注冊自定義BeanPostProcessor 注冊自定義BeanFactoryPostProcessor送粱,實現(xiàn)BeanFactoryAware接口
1. BeanPostProcessor
  • bean
package com.lyc.cn.v2.day02.processor.bean;

import com.lyc.cn.v2.day01.Dog;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;

/**
 * 繼承BeanPostProcessor接口并重寫其方法
 * @author: LiYanChao
 * @create: 2018-09-06 14:56
 */
public class MyBeanPostProcessorOne implements BeanPostProcessor, Ordered {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor第" + getOrder() + "次被調(diào)動\n");
        if (bean instanceof Dog) {
            ((Dog) bean).setName("強強");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof Dog) {
            ((Dog) bean).setAge(5);
        }
        return bean;
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

package com.lyc.cn.v2.day02.processor.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;

/**
 * 繼承BeanPostProcessor接口并重寫其方法
 * @author: LiYanChao
 * @create: 2018-09-06 14:56
 */
public class MyBeanPostProcessorTwo implements BeanPostProcessor, Ordered {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor第" + getOrder() + "次被調(diào)動");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public int getOrder() {
        return 2;
    }
}

2. BeanFactoryPostProcessor
package com.lyc.cn.v2.day02.processor.factory;

import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.Ordered;

public class MyBeanFactoryPostProcessorOne implements BeanFactoryPostProcessor, Ordered {

    /**
     * 修改dog的name屬性值
     * 修改dog的作用域
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryPostProcessor第" + getOrder() + "次被調(diào)動");
        BeanDefinition bd = beanFactory.getBeanDefinition("dog");
        if (null != bd) {
            System.out.println("dog屬性值:" + bd.getPropertyValues().toString());
            MutablePropertyValues pv = bd.getPropertyValues();
            if (pv.contains("name")) {
                System.out.println("修改dog的name屬性值為強強");
                pv.addPropertyValue("name", "強強");
            }
            System.out.println("修改dog的作用域為prototype\n");
            bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
        }
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

package com.lyc.cn.v2.day02.processor.factory;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.Ordered;

public class MyBeanFactoryPostProcessorTwo implements BeanFactoryPostProcessor, Ordered {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryPostProcessor第" + getOrder() + "次被調(diào)動");
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

  • xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd" profile="dev">

    <bean id="dog" class="com.lyc.cn.v2.day01.Dog">
        <!-- 指定構(gòu)造器參數(shù) index對應(yīng)構(gòu)造器中參數(shù)的位置 -->
        <!-- 也可以通過指定參數(shù)類型褪贵,指定參數(shù)名稱來注入屬性-->
        <constructor-arg index="0" value="小明"/>
        <constructor-arg index="1" value="3"/>
    </bean>

    <!-- =====beanPostProcessor配置begin =====-->
    <bean id="myBeanPostProcessorOne" class="com.lyc.cn.v2.day02.processor.bean.MyBeanPostProcessorOne"/>
    <bean id="myBeanPostProcessorTwo" class="com.lyc.cn.v2.day02.processor.bean.MyBeanPostProcessorTwo"/>
    <!-- =====beanPostProcessor配置end =====-->

    <!-- =====beanFactoryPostProcessor配置begin =====-->
    <!--注冊第一個后置工廠處理器-->
    <bean id="myBeanFactoryPostProcessorOne" class="com.lyc.cn.v2.day02.processor.factory.MyBeanFactoryPostProcessorOne"/>
    <!--注冊第二個后置工廠處理器-->
    <bean id="myBeanFactoryPostProcessorTwo" class="com.lyc.cn.v2.day02.processor.factory.MyBeanFactoryPostProcessorTwo"/>
    <!-- =====beanFactoryPostProcessor配置end =====-->

</beans>
  • 測試
package com.lyc.cn.v2.day02;

import com.lyc.cn.v2.day01.Dog;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;

/**
 * @author: LiYanChao
 * @create: 2018-09-07 23:40
 */
public class MyTest {
    private XmlBeanFactory xmlBeanFactory;

    @Before
    public void initXmlBeanFactory() {
        System.setProperty("spring.profiles.active", "dev");
        System.out.println("\n========測試方法開始=======\n");
        xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("v2/day01.xml"));
    }

    @After
    public void after() {
        System.out.println("\n========測試方法結(jié)束=======\n");
    }

    @Test
    public void test1() {
        // 測試BeanPostProcessor
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("v2/day02.xml");
        Dog dog = applicationContext.getBean("dog", Dog.class);
        dog.sayHello();
    }


    @Test
    public void test2() {
        // 測試BeanFactoryPostProcessor
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("v2/day02.xml");
        Dog dog = applicationContext.getBean("dog", Dog.class);
        dog.sayHello();
    }

}

  • 結(jié)果
    為了不影響測試結(jié)果,需要將BeanPostProcessor和BeanFactoryPostProcessor分開測試抗俄,測試test1時將test2的xml配置注釋掉脆丁,反之亦然。

test1-->

========測試方法開始=======

BeanPostProcessor第1次被調(diào)動

BeanPostProcessor第2次被調(diào)動
大家好, 我叫強強, 我今年5歲了

========測試方法結(jié)束=======

test2-->

========測試方法開始=======

BeanFactoryPostProcessor第0次被調(diào)動
dog屬性值:PropertyValues: length=0
修改dog的作用域為prototype

BeanFactoryPostProcessor第1次被調(diào)動
大家好, 我叫小明, 我今年3歲了

========測試方法結(jié)束=======
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末动雹,一起剝皮案震驚了整個濱河市槽卫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌胰蝠,老刑警劉巖晒夹,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異姊氓,居然都是意外死亡,警方通過查閱死者的電腦和手機喷好,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門翔横,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人梗搅,你說我怎么就攤上這事禾唁⌒Ю溃” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵荡短,是天一觀的道長丐枉。 經(jīng)常有香客問我,道長掘托,這世上最難降的妖魔是什么瘦锹? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮闪盔,結(jié)果婚禮上弯院,老公的妹妹穿的比我還像新娘。我一直安慰自己泪掀,他們只是感情好听绳,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著异赫,像睡著了一般椅挣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上塔拳,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天鼠证,我揣著相機與錄音,去河邊找鬼蝙斜。 笑死名惩,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的孕荠。 我是一名探鬼主播娩鹉,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼稚伍!你這毒婦竟也來了弯予?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤个曙,失蹤者是張志新(化名)和其女友劉穎锈嫩,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體垦搬,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡呼寸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了猴贰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片对雪。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖米绕,靈堂內(nèi)的尸體忽然破棺而出瑟捣,到底是詐尸還是另有隱情馋艺,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布迈套,位于F島的核電站捐祠,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏桑李。R本人自食惡果不足惜踱蛀,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芙扎。 院中可真熱鬧星岗,春花似錦、人聲如沸戒洼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽圈浇。三九已至寥掐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間磷蜀,已是汗流浹背召耘。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留褐隆,地道東北人污它。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像庶弃,于是被迫代替她去往敵國和親衫贬。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容