【Spring學習24】容器擴充套件點:後置處理器BeanFactoryPostProcessor
上篇說到的BeanPostProcessor(Bean後置處理器)常用在對bean內部的值進行修改;實現Bean的動態代理等。
BeanFactoryPostProcessor和BeanPostProcessor都是spring初始化bean時對外暴露的擴充套件點。但它們有什麼區別呢?
由《理解Bean生命週期》的圖可知:BeanFactoryPostProcessor是生命週期中最早被呼叫的,遠遠早於BeanPostProcessor。它在spring容器載入了bean的定義檔案之後,在bean例項化之前執行的。也就是說,Spring允許BeanFactoryPostProcessor在容器建立bean之前讀取bean配置元資料,並可進行修改。例如增加bean的屬性和值,重新設定bean是否作為自動裝配的侯選者,重設bean的依賴項等等。
在srping配置檔案中可以同時配置多個BeanFactoryPostProcessor,並通過在xml中註冊時設定’order’屬性來控制各個BeanFactoryPostProcessor的執行次序。
BeanFactoryPostProcessor介面定義如下:
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
介面只有一個方法postProcessBeanFactory。該方法的引數是ConfigurableListableBeanFactory型別,實際開發中,我們常使用它的getBeanDefinition()方法獲取某個bean的元資料定義:BeanDefinition。它有這些方法:
看個例子:
配置檔案中定義了一個bean:
<bean id="messi" class="twm.spring.LifecycleTest.footballPlayer">
<property name="name" value="Messi"></property>
<property name="team" value="Barcelona"></property>
</bean>
建立類beanFactoryPostProcessorImpl,實現介面BeanFactoryPostProcessor:
public class beanFactoryPostProcessorImpl implements BeanFactoryPostProcessor{
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("beanFactoryPostProcessorImpl");
BeanDefinition bdefine=beanFactory.getBeanDefinition("messi");
System.out.println(bdefine.getPropertyValues().toString());
MutablePropertyValues pv = bdefine.getPropertyValues();
if (pv.contains("team")) {
PropertyValue ppv= pv.getPropertyValue("name");
TypedStringValue obj=(TypedStringValue)ppv.getValue();
if(obj.getValue().equals("Messi")){
pv.addPropertyValue("team", "阿根延");
}
}
bdefine.setScope(BeanDefinition.SCOPE_PROTOTYPE);
}
}
呼叫類:
public static void main(String[] args) throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
footballPlayer obj = ctx.getBean("messi",footballPlayer.class);
System.out.println(obj.getTeam());
}
輸出:
PropertyValues: length=2; bean property ‘name’; bean property ‘team’
阿根延
在《PropertyPlaceholderConfigurer應用》提到的PropertyPlaceholderConfigurer這個類就是BeanFactoryPostProcessor介面的一個實現。它會在容器建立bean之前,將類定義中的佔位符(諸如${jdbc.url})用properties檔案對應的內容進行替換。