BeanPostProcessor


在Bean的屬性被Spring容器設定之後,您還有機會自訂一些對Bean的修正,您可以實作org.springframework.beans.factory.config.BeanPostProcessor介面:
package org.springframework.beans.factory.config;
public interface BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException;
    public Object postProcessAfterInitialization(Object bean, String name) throws BeansException;
}

postProcessBeforeInitialization()方法會在Bean初始化動作之前(例如InitializingBean的 afterPropertiesSet()方法或自定義的init方法)被呼叫,而postProcessAfterInitialization()方法會在Bean初始化之後立即被呼叫。

舉個例子來說,您可以實作一個大寫修正器,對於String型態的Bean屬性,無論在定義檔中是設定為大寫或小寫,在Bean屬性設定之後,您可以在大寫修正器中將所有的String改為大寫,例如:
  • UpperCaseModifier.java
package onlyfun.caterpillar;

import java.lang.reflect.Field;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class UpperCaseModifier implements BeanPostProcessor {

public Object postProcessBeforeInitialization(
Object bean, String name) throws BeansException {
Field[] fields = bean.getClass().getDeclaredFields();

for(int i = 0; i < fields.length; i++) {
if(fields[i].getType().equals(String.class)) {
fields[i].setAccessible(true);
try {
String original = (String) fields[i].get(bean);
fields[i].set(bean, original.toUpperCase());
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

return bean;
}

public Object postProcessAfterInitialization(
Object bean, String name) throws BeansException {
return bean;
}

}

假設您定義了這麼一個Bean類別:
  • HelloBean.java
package onlyfun.caterpillar; 

public class HelloBean {
private String helloWord;

public HelloBean() {
}

public void setHelloWord(String helloWord) {
this.helloWord = helloWord;
}
public String getHelloWord() {
return helloWord;
}
}

ApplicationContext會自動偵測您是否在定義檔中定義了實作BeanPostProcessor介面的類別,例如:
  • beans-config.xml
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="upperCaseModifier"
class="onlyfun.caterpillar.UpperCaseModifier"/>

<bean id="helloBean" class="onlyfun.caterpillar.HelloBean">
<property name="helloWord">
<value>Hello!</value>
</property>
</bean>
</beans>

Spring容器會在每一個Bean被初始化之前之後分別呼叫upperCaseModifier的 postProcessBeforeInitialization()方法與postProcessAfterInitialization()方法,以 對Bean進行指定的相關修正,可以實際來看看以下的測試程式:
  • SpringDemo.java
package onlyfun.caterpillar; 

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class SpringDemo {
public static void main(String[] args) {
ApplicationContext context =
new FileSystemXmlApplicationContext("beans-config.xml");

HelloBean hello =
(HelloBean) context.getBean("helloBean");
System.out.println(hello.getHelloWord());
}
}

執行結果如下:
HELLO!

雖然您在定義檔中的helloBean之helloWord屬性是設定小寫字母,但upperCaseModifier將之改為大寫字母了。