Spring原始碼學習--BeanFactoryPostProcessor介面
阿新 • • 發佈:2019-02-05
文章來源:
一 BeanFactoryPostProcessor介面介紹
Spring中BeanFactoryPostProcessor和BeanPostProcessor都是Spring初始化bean時對外暴露的擴充套件點。兩個介面從名字看起來很相似,但是作用及使用場景卻不同。
關於BeanPostProcessor介紹在這篇文章中已經講過:
Spring IoC容器允許BeanFactoryPostProcessor在容器例項化任何bean之前讀取bean的定義(配置元資料),並可以修改它。同時可以定義多個BeanFactoryPostProcessor,通過設定’order’屬性來確定各個BeanFactoryPostProcessor執行順序。
註冊一個BeanFactoryPostProcessor例項需要定義一個Java類來實現BeanFactoryPostProcessor介面,並重寫該介面的postProcessorBeanFactory方法。通過beanFactory可以獲取bean的定義資訊,並可以修改bean的定義資訊。這點是和BeanPostProcessor最大區別.
public interface BeanFactoryPostProcessor {
/**
* 獲取beanFactory,這樣在真正使用容器之前可以對一些bean做一些初始化操作
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
二 BeanFactoryPostProcessor簡單例項
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:用來註冊自定義的屬性編輯器