Spring BeanPostProcessor类 (在Spring实例化bean的前后执行一些附加操作)

在Spring实例化bean的前后执行一些附加操作。 

有时,你会发现需要立刻在Spring实例化一个bean的前后执行一些附件操作。这些操作可以简单到修改一个bean,也可以复杂到返回一个完全不同的对象。 
BeanPostProcessor接口包含两个方法: 
postProcessBeforeInitialization:在Spring调用任何bean的初始化钩子(例如InitializingBean.afterPropertiesSet或者init方法)之前被调用。 
postProcessAfterInitialization:Spring在成功完成嵌入初始化以后调用他。 

例子1: 
我们声明了一个实现了BeanPostProcessor接口的类InitDestroyAnnotationBeanPostProcessor,这个类支持声明式的指定注解规则(默认为JSR 250注解) 
  1. public class SimpleBean {  
  2.   
  3.     @PostConstruct  
  4.     public void initialize() {  
  5.         System.out.println("Initializing bean " + getClass());  
  6.     }  
  7.   
  8.     @PreDestroy  
  9.     public void cleanUp() {  
  10.         System.out.println("Cleaning up bean " + getClass());  
  11.     }  
  12.   
  13. }  

配置:
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="  
  5.                 http://www.springframework.org/schema/beans  
  6.                 http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.       
  8.     <bean id="simpleBean" class="com.apress.prospring2.ch04.bpp.SimpleBean"/>  
  9.     <bean id="bpp" class="org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor">  
  10.         <property name="initAnnotationType" value="javax.annotation.PostConstruct"/>  
  11.         <property name="destroyAnnotationType" value="javax.annotation.PreDestroy"/>  
  12.     </bean>  
  13.   
  14. </beans>  

调用: 
  1. public class SimpleBeanDemo {  
  2.   
  3.     public static void main(String[] args) {  
  4.         ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory(  
  5.                 new ClassPathResource("/META-INF/spring/bpp-context.xml")  
  6.         );  
  7.         registerPostProcessor(beanFactory, "bpp");  
  8.   
  9.         SimpleBean sb = (SimpleBean)beanFactory.getBean("simpleBean");  
  10.         System.out.println(sb);  
  11.   
  12.         beanFactory.destroySingletons();  
  13.     }  
  14.   
  15.     private static void registerPostProcessor(ConfigurableListableBeanFactory beanFactory, String beanName) {  
  16.         BeanPostProcessor bpp = (BeanPostProcessor) beanFactory.getBean(beanName);  
  17.         beanFactory.addBeanPostProcessor(bpp);  
  18.     }  
  19.   
  20. }  




例子2:自己实现一个BeanPostProcessor接口(改变bean的一个字段数据) 
(例子的实现是像上面的例子一样,自己定义一个时间注解的实现)
  1. package cn.partner4java.beanpostprocessor;  
  2.   
  3. import java.lang.annotation.ElementType;  
  4. import java.lang.annotation.Retention;  
  5. import java.lang.annotation.RetentionPolicy;  
  6. import java.lang.annotation.Target;  
  7.   
  8. /** 
  9. * 声明一个运行时字段注解 
  10. * @author partner4java 
  11. * 
  12. */  
  13. @Retention(RetentionPolicy.RUNTIME)  
  14. @Target(ElementType.FIELD)  
  15. public @interface TimeStamp {  
  16. }  
  1. package cn.partner4java.beanpostprocessor;  
  2.   
  3. import java.util.Date;  
  4.   
  5. import javax.annotation.PostConstruct;  
  6. import javax.annotation.PreDestroy;  
  7.   
  8. /** 
  9. * 指定交给Spring管理的bean 
  10. * @author partner4java 
  11. * 
  12. */  
  13. public class SimpleBean {  
  14.     //自定义的注解  
  15.     @TimeStamp  
  16.     Date createDate;  
  17.       
  18.     //spring中InitDestroyAnnotationBeanPostProcessor实现对bean init替代的注解  
  19.     @PostConstruct  
  20.     public void initialize(){  
  21.         System.out.println("initialize: " + getClass());  
  22.     }  
  23.       
  24.     //spring中InitDestroyAnnotationBeanPostProcessor实现对bean destory替代的注解  
  25.     @PreDestroy  
  26.     public void cleanup(){  
  27.         System.out.println("cleanup: " + getClass());  
  28.     }  
  29.   
  30.     @Override  
  31.     public String toString() {  
  32.         return "SimpleBean [createDate=" + createDate + "]";  
  33.     }  
  34.       
  35. }  


编写一个BeanPostProcessor来检查每一个bean并为他们注解了日志字段设置当前日期:
  1. package cn.partner4java.beanpostprocessor;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.util.Date;  
  5.   
  6. import org.springframework.beans.BeansException;  
  7. import org.springframework.beans.factory.config.BeanPostProcessor;  
  8. import org.springframework.util.ReflectionUtils;  
  9.   
  10. /** 
  11. * 编写一个BeanPostProcessor来检查每一个bean并为他们注解了日志字段设置当前日期 
  12. * @author partner4java 
  13. * 
  14. */  
  15. public class TimestampingBeanPostProcessor implements BeanPostProcessor {  
  16.   
  17.     public Object postProcessBeforeInitialization(final Object bean, String beanName)  
  18.             throws BeansException {  
  19.         ReflectionUtils.doWithFields(bean.getClass(),   
  20.                 new ReflectionUtils.FieldCallback() {  
  21.                     public void doWith(Field field) throws IllegalArgumentException,  
  22.                             IllegalAccessException {  
  23.                         field.set(bean, new Date());  
  24.                     }  
  25.                 }, new ReflectionUtils.FieldFilter() {  
  26.                     public boolean matches(Field field) {  
  27.                         return field.getType() == Date.class && field.getAnnotation(TimeStamp.class) != null;  
  28.                     }  
  29.                 });  
  30.           
  31.         return bean;  
  32.     }  
  33.   
  34.     public Object postProcessAfterInitialization(Object bean, String beanName)  
  35.             throws BeansException {  
  36.         return bean;  
  37.     }  
  38.   
  39. }  


配置文件:
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="  
  5.                 http://www.springframework.org/schema/beans  
  6.                 http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.       
  8.     <bean id="simpleBean" class="cn.partner4java.beanpostprocessor.SimpleBean"/>  
  9.     <bean id="bpp1" class="org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor">  
  10.         <property name="initAnnotationType" value="javax.annotation.PostConstruct"/>  
  11.         <property name="destroyAnnotationType" value="javax.annotation.PreDestroy"/>  
  12.     </bean>  
  13.     <bean id="bpp2" class="cn.partner4java.beanpostprocessor.TimestampingBeanPostProcessor"/>  
  14.   
  15. </beans>  

调用:
  1. package cn.partner4java.beanpostprocessor;  
  2.   
  3. import javax.annotation.PreDestroy;  
  4.   
  5. import org.springframework.beans.factory.config.BeanPostProcessor;  
  6. import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;  
  7. import org.springframework.beans.factory.xml.XmlBeanFactory;  
  8. import org.springframework.core.io.ClassPathResource;  
  9.   
  10. public class SimpleBeanDemo {  
  11.   
  12.     public static void main(String[] args) {  
  13.         ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory(  
  14.                 new ClassPathResource("/META-INF/spring/spring-beanpostprocessor.xml")  
  15.         );  
  16.         registerPostProcessor(beanFactory, "bpp1");  
  17.         registerPostProcessor(beanFactory, "bpp2");  
  18.   
  19.         SimpleBean sb = (SimpleBean)beanFactory.getBean("simpleBean");  
  20.         System.out.println(sb);  
  21.   
  22.         //@PreDestroy是被这个方法调用执行的  
  23.         beanFactory.destroySingletons();  
  24.     }  
  25.   
  26.     private static void registerPostProcessor(ConfigurableListableBeanFactory beanFactory, String beanName) {  
  27.         BeanPostProcessor bpp = (BeanPostProcessor) beanFactory.getBean(beanName);  
  28.         beanFactory.addBeanPostProcessor(bpp);  
  29.     }  
  30.   
  31. }  
  32. //后台打印:  
  33. //initialize: class cn.partner4java.beanpostprocessor.SimpleBean  
  34. //SimpleBean [createDate=Tue Nov 15 16:18:33 CST 2011]  
  35. //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。
  1. public class SimpleBean {  
  2.     @Timestamp  
  3.     Date creationDate;  
  4.       
  5.     @Autowired  
  6.     String dependency;  
  7.   
  8.     @PostConstruct  
  9.     public void initialize() {  
  10.         System.out.println("Initializing bean " + getClass());  
  11.     }  
  12.   
  13.     @PreDestroy  
  14.     public void cleanUp() {  
  15.         System.out.println("Cleaning up bean " + getClass());  
  16.     }  
  17.   
  18.     @Override  
  19.     public String toString() {  
  20.         return "Bean was created at " + this.creationDate + " with " + this.dependency;  
  21.     }  
  22. }  

我们修改bean的类型:
  1. public class TypedDependencyBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {  
  2.   
  3.     public Class predictBeanType(Class beanClass, String beanName) {  
  4.         if (beanClass.equals(Dependency.class)) {  
  5.             return String.class;  
  6.         }  
  7.         return beanClass;  
  8.     }  
  9.   
  10.     public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {  
  11.         if (bean.getClass().equals(Dependency.class)) {  
  12.             return "Hello, world";  
  13.         }  
  14.         return bean;  
  15.     }  
  16.   
  17.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
  18.         return bean;  
  19.     }  
  20. }  

配置:
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xsi:schemaLocation="  
  5.                 http://www.springframework.org/schema/beans  
  6.                 http://www.springframework.org/schema/beans/spring-beans.xsd">  
  7.   
  8.     <bean id="dependency" class="com.apress.prospring2.ch04.bpp.Dependency"/>  
  9.     <bean id="simpleBean" class="com.apress.prospring2.ch04.bpp.SimpleBean"/>  
  10.     <bean id="bpp" class="org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor">  
  11.         <property name="initAnnotationType" value="javax.annotation.PostConstruct"/>  
  12.         <property name="destroyAnnotationType" value="javax.annotation.PreDestroy"/>  
  13.     </bean>  
  14.     <bean id="bpp2" class="com.apress.prospring2.ch04.bpp.TimestampingBeanPostProcessor"/>  
  15.     <bean id="bpp3" class="com.apress.prospring2.ch04.bpp.TypedDependencyBeanPostProcessor"/>  
  16.     <bean id="bpp4" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>  
  17.   
  18. </beans>  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值