在Spring实例化bean的前后执行一些附加操作。
有时,你会发现需要立刻在Spring实例化一个bean的前后执行一些附件操作。这些操作可以简单到修改一个bean,也可以复杂到返回一个完全不同的对象。
BeanPostProcessor接口包含两个方法:
postProcessBeforeInitialization:在Spring调用任何bean的初始化钩子(例如InitializingBean.afterPropertiesSet或者init方法)之前被调用。
postProcessAfterInitialization:Spring在成功完成嵌入初始化以后调用他。
例子1:
我们声明了一个实现了BeanPostProcessor接口的类InitDestroyAnnotationBeanPostProcessor,这个类支持声明式的指定注解规则(默认为JSR 250注解)
配置:
调用:
例子2:自己实现一个BeanPostProcessor接口(改变bean的一个字段数据)
(例子的实现是像上面的例子一样,自己定义一个时间注解的实现)
编写一个BeanPostProcessor来检查每一个bean并为他们注解了日志字段设置当前日期:
配置文件:
调用:
例子3:
Spring自带的简单支持,例子中完全修改了一个bean的类型,从Dependency类转变为了String类型的字符串。(改变一个bean的类型)
(org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor)
(继承public abstract class InstantiationAwareBeanPostProcessorAdapter implements SmartInstantiationAwareBeanPostProcessor。
这让我们使用这个回调处理适配器来实现能够预测回调处理bean的类型的BeanPostProcessor接口)
我们在下面的定义中指定了一个自动关联的注解,但是我们系统中并没有String类型的dependency关联,只要一个Dependency类交给了Spring。
我们修改bean的类型:
配置:
有时,你会发现需要立刻在Spring实例化一个bean的前后执行一些附件操作。这些操作可以简单到修改一个bean,也可以复杂到返回一个完全不同的对象。
BeanPostProcessor接口包含两个方法:
postProcessBeforeInitialization:在Spring调用任何bean的初始化钩子(例如InitializingBean.afterPropertiesSet或者init方法)之前被调用。
postProcessAfterInitialization:Spring在成功完成嵌入初始化以后调用他。
例子1:
我们声明了一个实现了BeanPostProcessor接口的类InitDestroyAnnotationBeanPostProcessor,这个类支持声明式的指定注解规则(默认为JSR 250注解)
- public class SimpleBean {
- @PostConstruct
- public void initialize() {
- System.out.println("Initializing bean " + getClass());
- }
- @PreDestroy
- public void cleanUp() {
- System.out.println("Cleaning up bean " + getClass());
- }
- }
配置:
- <?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">
- <bean id="simpleBean" class="com.apress.prospring2.ch04.bpp.SimpleBean"/>
- <bean id="bpp" class="org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor">
- <property name="initAnnotationType" value="javax.annotation.PostConstruct"/>
- <property name="destroyAnnotationType" value="javax.annotation.PreDestroy"/>
- </bean>
- </beans>
调用:
- public class SimpleBeanDemo {
- public static void main(String[] args) {
- ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory(
- new ClassPathResource("/META-INF/spring/bpp-context.xml")
- );
- registerPostProcessor(beanFactory, "bpp");
- SimpleBean sb = (SimpleBean)beanFactory.getBean("simpleBean");
- System.out.println(sb);
- beanFactory.destroySingletons();
- }
- private static void registerPostProcessor(ConfigurableListableBeanFactory beanFactory, String beanName) {
- BeanPostProcessor bpp = (BeanPostProcessor) beanFactory.getBean(beanName);
- beanFactory.addBeanPostProcessor(bpp);
- }
- }
例子2:自己实现一个BeanPostProcessor接口(改变bean的一个字段数据)
(例子的实现是像上面的例子一样,自己定义一个时间注解的实现)
- package cn.partner4java.beanpostprocessor;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- /**
- * 声明一个运行时字段注解
- * @author partner4java
- *
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.FIELD)
- public @interface TimeStamp {
- }
- package cn.partner4java.beanpostprocessor;
- import java.util.Date;
- import javax.annotation.PostConstruct;
- import javax.annotation.PreDestroy;
- /**
- * 指定交给Spring管理的bean
- * @author partner4java
- *
- */
- public class SimpleBean {
- //自定义的注解
- @TimeStamp
- Date createDate;
- //spring中InitDestroyAnnotationBeanPostProcessor实现对bean init替代的注解
- @PostConstruct
- public void initialize(){
- System.out.println("initialize: " + getClass());
- }
- //spring中InitDestroyAnnotationBeanPostProcessor实现对bean destory替代的注解
- @PreDestroy
- public void cleanup(){
- System.out.println("cleanup: " + getClass());
- }
- @Override
- public String toString() {
- return "SimpleBean [createDate=" + createDate + "]";
- }
- }
编写一个BeanPostProcessor来检查每一个bean并为他们注解了日志字段设置当前日期:
- package cn.partner4java.beanpostprocessor;
- import java.lang.reflect.Field;
- import java.util.Date;
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.BeanPostProcessor;
- import org.springframework.util.ReflectionUtils;
- /**
- * 编写一个BeanPostProcessor来检查每一个bean并为他们注解了日志字段设置当前日期
- * @author partner4java
- *
- */
- public class TimestampingBeanPostProcessor implements BeanPostProcessor {
- public Object postProcessBeforeInitialization(final Object bean, String beanName)
- throws BeansException {
- ReflectionUtils.doWithFields(bean.getClass(),
- new ReflectionUtils.FieldCallback() {
- public void doWith(Field field) throws IllegalArgumentException,
- IllegalAccessException {
- field.set(bean, new Date());
- }
- }, new ReflectionUtils.FieldFilter() {
- public boolean matches(Field field) {
- return field.getType() == Date.class && field.getAnnotation(TimeStamp.class) != null;
- }
- });
- return bean;
- }
- public Object postProcessAfterInitialization(Object bean, String beanName)
- throws BeansException {
- return bean;
- }
- }
配置文件:
- <?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">
- <bean id="simpleBean" class="cn.partner4java.beanpostprocessor.SimpleBean"/>
- <bean id="bpp1" class="org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor">
- <property name="initAnnotationType" value="javax.annotation.PostConstruct"/>
- <property name="destroyAnnotationType" value="javax.annotation.PreDestroy"/>
- </bean>
- <bean id="bpp2" class="cn.partner4java.beanpostprocessor.TimestampingBeanPostProcessor"/>
- </beans>
调用:
- package cn.partner4java.beanpostprocessor;
- import javax.annotation.PreDestroy;
- import org.springframework.beans.factory.config.BeanPostProcessor;
- import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
- import org.springframework.beans.factory.xml.XmlBeanFactory;
- import org.springframework.core.io.ClassPathResource;
- public class SimpleBeanDemo {
- public static void main(String[] args) {
- ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory(
- new ClassPathResource("/META-INF/spring/spring-beanpostprocessor.xml")
- );
- registerPostProcessor(beanFactory, "bpp1");
- registerPostProcessor(beanFactory, "bpp2");
- SimpleBean sb = (SimpleBean)beanFactory.getBean("simpleBean");
- System.out.println(sb);
- //@PreDestroy是被这个方法调用执行的
- beanFactory.destroySingletons();
- }
- private static void registerPostProcessor(ConfigurableListableBeanFactory beanFactory, String beanName) {
- BeanPostProcessor bpp = (BeanPostProcessor) beanFactory.getBean(beanName);
- beanFactory.addBeanPostProcessor(bpp);
- }
- }
- //后台打印:
- //initialize: class cn.partner4java.beanpostprocessor.SimpleBean
- //SimpleBean [createDate=Tue Nov 15 16:18:33 CST 2011]
- //cleanup: class cn.partner4java.beanpostprocessor.SimpleBean
例子3:
Spring自带的简单支持,例子中完全修改了一个bean的类型,从Dependency类转变为了String类型的字符串。(改变一个bean的类型)
(org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor)
(继承public abstract class InstantiationAwareBeanPostProcessorAdapter implements SmartInstantiationAwareBeanPostProcessor。
这让我们使用这个回调处理适配器来实现能够预测回调处理bean的类型的BeanPostProcessor接口)
我们在下面的定义中指定了一个自动关联的注解,但是我们系统中并没有String类型的dependency关联,只要一个Dependency类交给了Spring。
- public class SimpleBean {
- @Timestamp
- Date creationDate;
- @Autowired
- String dependency;
- @PostConstruct
- public void initialize() {
- System.out.println("Initializing bean " + getClass());
- }
- @PreDestroy
- public void cleanUp() {
- System.out.println("Cleaning up bean " + getClass());
- }
- @Override
- public String toString() {
- return "Bean was created at " + this.creationDate + " with " + this.dependency;
- }
- }
我们修改bean的类型:
- public class TypedDependencyBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
- public Class predictBeanType(Class beanClass, String beanName) {
- if (beanClass.equals(Dependency.class)) {
- return String.class;
- }
- return beanClass;
- }
- public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
- if (bean.getClass().equals(Dependency.class)) {
- return "Hello, world";
- }
- return bean;
- }
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- return bean;
- }
- }
配置:
- <?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">
- <bean id="dependency" class="com.apress.prospring2.ch04.bpp.Dependency"/>
- <bean id="simpleBean" class="com.apress.prospring2.ch04.bpp.SimpleBean"/>
- <bean id="bpp" class="org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor">
- <property name="initAnnotationType" value="javax.annotation.PostConstruct"/>
- <property name="destroyAnnotationType" value="javax.annotation.PreDestroy"/>
- </bean>
- <bean id="bpp2" class="com.apress.prospring2.ch04.bpp.TimestampingBeanPostProcessor"/>
- <bean id="bpp3" class="com.apress.prospring2.ch04.bpp.TypedDependencyBeanPostProcessor"/>
- <bean id="bpp4" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
- </beans>