Spring中BeanFactoryPostProcessor和BeanPostProcessor都是Spring初始化bean時對外暴露的擴展點。兩個接口從名字看起來很相似,但是作用及使用場景卻不同。
關於BeanPostProcessor介紹在這篇文章中已經講過:http://www.cnblogs.com/sishang/p/6576665.html 這里主要介紹BeanFactoryPostProcessor。
Spring IoC容器允許BeanFactoryPostProcessor在容器實例化任何bean之前讀取bean的定義(配置元數據),並可以修改它。同時可以定義多個BeanFactoryPostProcessor,通過設置'order'屬性來確定各個BeanFactoryPostProcessor執行順序。
注冊一個BeanFactoryPostProcessor實例需要定義一個Java類來實現BeanFactoryPostProcessor接口,並重寫該接口的postProcessorBeanFactory方法。通過beanFactory可以獲取bean的定義信息,並可以修改bean的定義信息。這點是和BeanPostProcessor最大區別
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.java
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:
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接口中方法。
***************************************************************************************************************************
在Spring中內置了一些BeanFactoryPostProcessor實現類:
- org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
- org.springframework.beans.factory.config.PropertyOverrideConfigurer
- org.springframework.beans.factory.config.CustomEditorConfigurer:用來注冊自定義的屬性編輯器
備注:下一篇將會介紹PropertyPlaceHoldConfigurer在Spring機制中如何讀取配置文件的信息