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實現類:
備註:下一篇將會介紹PropertyPlaceHoldConfigurer在Spring機制中如何讀取配置文件的信息