ITEEDU

Spring Gossip: 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将之改为大写字母了。