一知识点
Bean后处理器允许在初始化回调方法前后进行额外的Bean处理Bean后处理器的主要特性是逐个处理IoC容器中的所有Bean实例而不只是单个Bean实例一般来说Bean后处理器用于检查Bean属性的有效性或根据特定条件修改Bean属性
Bean后处理器的基本要求是实现BeanPostProcessor接口通过实现postProcessBeforeInitialization() 和 postProcessAfterInitialization() 方法可以在初始化回调方法前后处理所有BeanSpring将在调用初始化回调方法前后向这两个方法传递每个Bean实例步骤如下
()构造函数或者工厂方法创建Bean实例
()为Bean属性设值和Bean引用
()调用感知接口中定义的设值方法
()将Bean实例传递给每个Bean后处理器中的postProcessBeforeInitialization()方法
()调用初始化回调方法
()将Bean实例传递给每个Bean后处理器中的postProcessAfterInitialization()方法
()Bean准备就绪可以使用
()容器关闭时调用销毁回调函数
使用Bean工厂作为IoC容器时Bean后处理器只能编程注册即通过addBeanPostProcessor方法注册如果使用应用程序上下文只需要在Bean配置文件中声明一个处理器实例它就会自动注册
二代码示例
StorageConfig标记接口
[java]
package deprojectjackiespringrecipesnotespringadvancedioc;
/**
* 标记接口让Bean后处理器区分应检查的Bean
* @author jackie
*
*/
public interface StorageConfig {
public String getPath();
}
package deprojectjackiespringrecipesnotespringadvancedioc;
/**
* 标记接口让Bean后处理器区分应检查的Bean
* @author jackie
*
*/
public interface StorageConfig {
public String getPath();
} Cashier类
[java]
package deprojectjackiespringrecipesnotespringadvancedioc;
import javaioBufferedWriter;
import javaioFile;
import javaioFileWriter;
import javaioIOException;
import javautilDate;
import orgspringframeworkbeansfactoryBeanNameAware;
/**
* Cashier类实现BeanNameAware感知接口和StorageConfig标记接口
* @author jackie
*
*/
public class Cashier implements BeanNameAware StorageConfig {
private String name;
private BufferedWriter writer;
private String path;
public void setPath(String path) {
thispath = path;
}
public void openFile() throws IOException {
File file = new File(path name + txt);
FileWriter fw = new FileWriter(file true);
writer = new BufferedWriter(fw);
}
public void checkout(ShoppingCart cart) throws IOException {
double total = ;
for (Product product : cartgetItems()) {
total += productgetPrice();
}
writerwrite(new Date() + \t + total + \r\n);
writerflush();
}
public void closeFile() throws IOException {
writerclose();
}
@Override
public String getPath() {
return path;
}
@Override
public void setBeanName(String beanName) {
thisname = beanName;
}
}
package deprojectjackiespringrecipesnotespringadvancedioc;
import javaioBufferedWriter;
import javaioFile;
import javaioFileWriter;
import javaioIOException;
import javautilDate;
import orgspringframeworkbeansfactoryBeanNameAware;
/**
* Cashier类实现BeanNameAware感知接口和StorageConfig标记接口
* @author jackie
*
*/
public class Cashier implements BeanNameAware StorageConfig {
private String name;
private BufferedWriter writer;
private String path;
public void setPath(String path) {
thispath = path;
}
public void openFile() throws IOException {
File file = new File(path name + txt);
FileWriter fw = new FileWriter(file true);
writer = new BufferedWriter(fw);
}
public void checkout(ShoppingCart cart) throws IOException {
double total = ;
for (Product product : cartgetItems()) {
total += productgetPrice();
}
writerwrite(new Date() + \t + total + \r\n);
writerflush();
}
public void closeFile() throws IOException {
writerclose();
}
@Override
public String getPath() {
return path;
}
@Override
public void setBeanName(String beanName) {
thisname = beanName;
}
}
PathCheckingBeanPostProcessor自定义Bean后处理器
[java]
package deprojectjackiespringrecipesnotespringadvancedioc;
import javaioFile;
import orgspringframeworkbeansBeansException;
import orgspringframewonfigBeanPostProcessor;
/**
* 通用的组件确保文件在打开之前存在
* @author jackie
*
*/
public class PathCheckingBeanPostProcessor implements BeanPostProcessor {
/**
* 在文件打开之前进行路径检查
* 须返回所处理的Bean的一个实例
*/
@Override
public Object postProcessBeforeInitialization(Object bean String beanName)
throws BeansException {
// 如果Bean实现了StorageConfig接口检查路径是否存在
if (bean instanceof StorageConfig) {
String path = ((StorageConfig)bean)getPath();
File file = new File(path);
if (!fileexists()) {
filemkdirs();
}
}
return bean;
}
/**
* 即使什么都不做也必须返回原来的Bean实例
*/
@Override
public Object postProcessAfterInitialization(Object bean String beanName)
throws BeansException {
return bean;
}
}
package deprojectjackiespringrecipesnotespringadvancedioc;
import javaioFile;
import orgspringframeworkbeansBeansException;
import orgspringframewonfigBeanPostProcessor;
/**
* 通用的组件确保文件在打开之前存在
* @author jackie
*
*/
public class PathCheckingBeanPostProcessor implements BeanPostProcessor {
/**
* 在文件打开之前进行路径检查
* 须返回所处理的Bean的一个实例
*/
@Override
public Object postProcessBeforeInitialization(Object bean String beanName)
throws BeansException {
// 如果Bean实现了StorageConfig接口检查路径是否存在
if (bean instanceof StorageConfig) {
String path = ((StorageConfig)bean)getPath();
File file = new File(path);
if (!fileexists()) {
filemkdirs();
}
}
return bean;
}
/**
* 即使什么都不做也必须返回原来的Bean实例
*/
@Override
public Object postProcessAfterInitialization(Object bean String beanName)
throws BeansException {
return bean;
}
}Bean配置
[html]
<?xml version= encoding=UTF?>
<beans xmlns=
xmlns:xsi=instance
xsi:schemaLocation= beansxsd>
<! 注册Bean后处理器 >
<bean class=deprojectjackiespringrecipesnotespringadvancediocPathCheckingBeanPostProcessor />
<bean id=aaa class=deprojectjackiespringrecipesnotespringadvancediocBattery>
<property name=name value=AAA />
<property name=price value= />
</bean>
<bean id=cdrw class=deprojectjackiespringrecipesnotespringadvancediocBattery>
<property name=name value=CDRW />
<property name=price value= />
</bean>
<bean id=dvdrw class=deprojectjackiespringrecipesnotespringadvancediocBattery>
<property name=name value=DVDRW />
<property name=price value= />
</bean>
<bean id=shoppingCart class=deprojectjackiespringrecipesnotespringadvancediocShoppingCart scope=prototype />
<bean id=cashier class=deprojectjackiespringrecipesnotespringadvancediocCashier initmethod=openFile destroymethod=closeFile >
<property name=path value=c:/cashier />
</bean>
</beans>
<?xml version= encoding=UTF?>
<beans xmlns=
xmlns:xsi=instance
xsi:schemaLocation= beansxsd>
<! 注册Bean后处理器 >
<bean class=deprojectjackiespringrecipesnotespringadvancediocPathCheckingBeanPostProcessor />
<bean id=aaa class=deprojectjackiespringrecipesnotespringadvancediocBattery>
<property name=name value=AAA />
<property name=price value= />
</bean>
<bean id=cdrw class=deprojectjackiespringrecipesnotespringadvancediocBattery>
<property name=name value=CDRW />
<property name=price value= />
</bean>
<bean id=dvdrw class=deprojectjackiespringrecipesnotespringadvancediocBattery>
<property name=name value=DVDRW />
<property name=price value= />
</bean>
<bean id=shoppingCart class=deprojectjackiespringrecipesnotespringadvancediocShoppingCart scope=prototype />
<bean id=cashier class=deprojectjackiespringrecipesnotespringadvancediocCashier initmethod=openFile destroymethod=closeFile >
<property name=path value=c:/cashier />
</bean>
</beans>测试类
[java]
package deprojectjackiespringrecipesnotespringadvancedioc;
import javaioIOException;
import orgjunitTest;
import orgntextApplicationContext;
import orgntextsupportClassPathXmlApplicationContext;
/**
* @author jackie
*
*/
public class BeanPostProcessorTest {
@Test
public void testBeanPostProcessor() throws IOException {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(applicationContextxml);
Product aaa = (Product) applicationContextgetBean(aaa);
Product cdrw = (Product) applicationContextgetBean(cdrw);
Product dvdrw = (Product) applicationContextgetBean(dvdrw);
ShoppingCart shoppingCart = (ShoppingCart) applicationContextgetBean(shoppingCart);
shoppingCartaddItem(aaa);
shoppingCartaddItem(cdrw);
shoppingCartaddItem(dvdrw);
Cashier cashier = (Cashier) applicationContextgetBean(cashier);
cashiercheckout(shoppingCart);
}
}
package deprojectjackiespringrecipesnotespringadvancedioc;
import javaioIOException;
import orgjunitTest;
import orgntextApplicationContext;
import orgntextsupportClassPathXmlApplicationContext;
/**
* @author jackie
*
*/
public class BeanPostProcessorTest {
@Test
public void testBeanPostProcessor() throws IOException {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(applicationContextxml);
Product aaa = (Product) applicationContextgetBean(aaa);
Product cdrw = (Product) applicationContextgetBean(cdrw);
Product dvdrw = (Product) applicationContextgetBean(dvdrw);
ShoppingCart shoppingCart = (ShoppingCart) applicationContextgetBean(shoppingCart);
shoppingCartaddItem(aaa);
shoppingCartaddItem(cdrw);
shoppingCartaddItem(dvdrw);
Cashier cashier = (Cashier) applicationContextgetBean(cashier);
cashiercheckout(shoppingCart);
}
}
注书上说如果使用JSR注解@PostConstruct和@PreDestroy并且一个CommonAnnotationBeanPostProcessor实例调用初始化方法那么PathCheckingBeanPostProcessor不能正常工作因为它的默认优先级低于CommonAnnotationBeanPostProcessor经我实践证明PathCheckingBeanPostProcessor仍然可以正常工作