Spring點滴十一:Spring中BeanFactoryPostProcessor和BeanPostProcessor區別

     Spring中BeanFactoryPostProcessor和BeanPostProcessor都是Spring初始化bean時對外暴露的擴展點。兩個接口從名字看起來很類似,可是做用及使用場景卻不一樣。html

關於BeanPostProcessor介紹在這篇文章中已經講過:http://www.cnblogs.com/sishang/p/6576665.html 這裏主要介紹BeanFactoryPostProcessor。java

    Spring IoC容器容許BeanFactoryPostProcessor在容器實例化任何bean以前讀取bean的定義(配置元數據),並能夠修改它。同時能夠定義多個BeanFactoryPostProcessor,經過設置'order'屬性來肯定各個BeanFactoryPostProcessor執行順序。spring

   註冊一個BeanFactoryPostProcessor實例須要定義一個Java類來實現BeanFactoryPostProcessor接口,並重寫該接口的postProcessorBeanFactory方法。經過beanFactory能夠獲取bean的定義信息,並能夠修改bean的定義信息。這點是和BeanPostProcessor最大區別app

    public interface BeanFactoryPostProcessor {  
      
        /** 
         * Modify the application context's internal bean factory after its standard 
         * initialization. All bean definitions will have been loaded, but no beans 
         * will have been instantiated yet. This allows for overriding or adding 
         * properties even to eager-initializing beans. 
         * @param beanFactory the bean factory used by the application context 
         * @throws org.springframework.beans.BeansException in case of errors 
         */  
        void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;  
      
    }  

spring.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 支持Spring註解 -->
    <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
<!-- 註冊一個BeanPostProcessor --> <bean id="postProcessor" class="com.test.spring.PostProcessor"/> <!-- 註冊一個BeanFactoryPostProcessor --> <bean id="factoryPostProcessor" class="com.test.spring.FactoryPostProcessor"/>
<!-- 普通bean --> <bean id="beanFactoryPostProcessorTest" class="com.test.spring.BeanFactoryPostProcessorTest"> <property name="name" value="張三"/> <property name="sex" value="男"/> </bean> </beans>

BeanPostProcessor.javaide

package com.test.spring;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
 * bean後置處理器
 * @author zss
 *
 */
public class PostProcessor implements BeanPostProcessor{

    @Override
    public Object postProcessBeforeInitialization(Object bean,
            String beanName) throws BeansException {
        System.out.println("後置處理器處理bean=【"+beanName+"】開始");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean,
            String beanName) throws BeansException {
        System.out.println("後置處理器處理bean=【"+beanName+"】完畢!");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return bean;
    }
}
BeanFactoryPostProcessor.java
package com.test.spring;

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

public class FactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(
            ConfigurableListableBeanFactory configurableListableBeanFactory)
            throws BeansException {
        System.out.println("******調用了BeanFactoryPostProcessor");
        String[] beanStr = configurableListableBeanFactory
                .getBeanDefinitionNames();
        for (String beanName : beanStr) {
            if ("beanFactoryPostProcessorTest".equals(beanName)) {
                BeanDefinition beanDefinition = configurableListableBeanFactory
                        .getBeanDefinition(beanName);
                MutablePropertyValues m = beanDefinition.getPropertyValues();
                if (m.contains("name")) {
                    m.addPropertyValue("name", "趙四");
System.out.println("》》》修改了name屬性初始值了"); } } } } }
BeanFactoryPostProcessorTest.java 
package com.test.spring;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class BeanFactoryPostProcessorTest implements InitializingBean,DisposableBean,BeanNameAware,BeanFactoryAware {
    private String name;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public void setBeanFactory(BeanFactory paramBeanFactory)
            throws BeansException {
        System.out.println("》》》調用了BeanFactoryAware的setBeanFactory方法了");
    }

    @Override
    public void setBeanName(String paramString) {
        System.out.println("》》》調用了BeanNameAware的setBeanName方法了");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("》》》調用了DisposableBean的destroy方法了");        
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("》》》調用了Initailization的afterPropertiesSet方法了");
    }

    @Override
    public String toString() {
        return "BeanFactoryPostProcessorTest [name=" + name + ", sex=" + sex
                + "]";
    }
}

Test case:post

package com.test.spring;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class T {
    ApplicationContext applicationcontext=null;
    @Before
    public void before() {
        System.out.println("》》》Spring ApplicationContext容器開始初始化了......");
        applicationcontext= new ClassPathXmlApplicationContext(new String[]{"spring-service.xml"});
        System.out.println("》》》Spring ApplicationContext容器初始化完畢了......");
    }
    @Test
    public void  test() {
        //BeanLifecycle beanLifecycle =applicationcontext.getBean("beanLifecycle",BeanLifecycle.class);
        BeanFactoryPostProcessorTest beanFactoryPostProcessorTest=applicationcontext.getBean(BeanFactoryPostProcessorTest.class);
        System.out.println(beanFactoryPostProcessorTest.toString());
    }
}

測試結果:測試

》》》Spring ApplicationContext容器開始初始化了......
2017-03-20 14:36:10  INFO:ClassPathXmlApplicationContext-Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@17ad352e: startup date [Mon Mar 20 14:36:10 CST 2017]; root of context hierarchy
2017-03-20 14:36:10  INFO:XmlBeanDefinitionReader-Loading XML bean definitions from class path resource [spring-service.xml]
******調用了BeanFactoryPostProcessor
》》》修改了name屬性初始值了
》》》調用了BeanNameAware的setBeanName方法了
》》》調用了BeanFactoryAware的setBeanFactory方法了
後置處理器處理bean=【beanFactoryPostProcessorTest】開始
後置處理器開始調用了
》》》調用了Initailization的afterPropertiesSet方法了
後置處理器處理bean=【beanFactoryPostProcessorTest】完畢!
後置處理器調用結束了
》》》Spring ApplicationContext容器初始化完畢了......
BeanFactoryPostProcessorTest [name=趙四, sex=男]
---------------------------------------------------------------------------------------------------------
從測試結果中能夠看到beanFactoryPostProcessorTest定義的name值由"張三"變爲"趙四",同時發現postProcessorBeanFactory方法執行順序先於BeanPostProcessor接口中方法。this

***************************************************************************************************************************spa

   在Spring中內置了一些BeanFactoryPostProcessor實現類:

  • org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
  • org.springframework.beans.factory.config.PropertyOverrideConfigurer
  • org.springframework.beans.factory.config.CustomEditorConfigurer:用來註冊自定義的屬性編輯器

     

    

    備註:下一篇將會介紹PropertyPlaceHoldConfigurer在Spring機制中如何讀取配置文件的信息

相關文章
相關標籤/搜索