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

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

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

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

配置:
  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. <bean id="simpleBean"class="com.apress.prospring2.ch04.bpp.SimpleBean"/>
  8. <bean id="bpp"class="org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor">
  9. <property name="initAnnotationType"value="javax.annotation.PostConstruct"/>
  10. <property name="destroyAnnotationType"value="javax.annotation.PreDestroy"/>
  11. </bean>
  12. </beans>

调用:
  1. publicclassSimpleBeanDemo {
  2. publicstaticvoidmain(String[] args) {
  3. ConfigurableListableBeanFactory beanFactory =newXmlBeanFactory(
  4. newClassPathResource("/META-INF/spring/bpp-context.xml")
  5. );
  6. registerPostProcessor(beanFactory,"bpp");
  7. SimpleBean sb = (SimpleBean)beanFactory.getBean("simpleBean");
  8. System.out.println(sb);
  9. beanFactory.destroySingletons();
  10. }
  11. privatestaticvoidregisterPostProcessor(ConfigurableListableBeanFactory beanFactory, String beanName) {
  12. BeanPostProcessor bpp = (BeanPostProcessor) beanFactory.getBean(beanName);
  13. beanFactory.addBeanPostProcessor(bpp);
  14. }
  15. }




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


编写一个BeanPostProcessor来检查每一个bean并为他们注解了日志字段设置当前日期:
  1. packagecn.partner4java.beanpostprocessor;
  2. importjava.lang.reflect.Field;
  3. importjava.util.Date;
  4. importorg.springframework.beans.BeansException;
  5. importorg.springframework.beans.factory.config.BeanPostProcessor;
  6. importorg.springframework.util.ReflectionUtils;
  7. /**
  8. * 编写一个BeanPostProcessor来检查每一个bean并为他们注解了日志字段设置当前日期
  9. * @author partner4java
  10. *
  11. */
  12. publicclassTimestampingBeanPostProcessorimplementsBeanPostProcessor {
  13. publicObject postProcessBeforeInitialization(finalObject bean, String beanName)
  14. throwsBeansException {
  15. ReflectionUtils.doWithFields(bean.getClass(),
  16. newReflectionUtils.FieldCallback() {
  17. publicvoiddoWith(Field field)throwsIllegalArgumentException,
  18. IllegalAccessException {
  19. field.set(bean,newDate());
  20. }
  21. },newReflectionUtils.FieldFilter() {
  22. publicbooleanmatches(Field field) {
  23. returnfield.getType() == Date.class&& field.getAnnotation(TimeStamp.class) !=null;
  24. }
  25. });
  26. returnbean;
  27. }
  28. publicObject postProcessAfterInitialization(Object bean, String beanName)
  29. throwsBeansException {
  30. returnbean;
  31. }
  32. }


配置文件:
  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. <bean id="simpleBean"class="cn.partner4java.beanpostprocessor.SimpleBean"/>
  8. <bean id="bpp1"class="org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor">
  9. <property name="initAnnotationType"value="javax.annotation.PostConstruct"/>
  10. <property name="destroyAnnotationType"value="javax.annotation.PreDestroy"/>
  11. </bean>
  12. <bean id="bpp2"class="cn.partner4java.beanpostprocessor.TimestampingBeanPostProcessor"/>
  13. </beans>

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

我们修改bean的类型:
  1. publicclassTypedDependencyBeanPostProcessorextendsInstantiationAwareBeanPostProcessorAdapter {
  2. publicClass predictBeanType(Class beanClass, String beanName) {
  3. if(beanClass.equals(Dependency.class)) {
  4. returnString.class;
  5. }
  6. returnbeanClass;
  7. }
  8. publicObject postProcessBeforeInitialization(finalObject bean,finalString beanName)throwsBeansException {
  9. if(bean.getClass().equals(Dependency.class)) {
  10. return"Hello, world";
  11. }
  12. returnbean;
  13. }
  14. publicObject postProcessAfterInitialization(Object bean, String beanName)throwsBeansException {
  15. returnbean;
  16. }
  17. }

配置:
  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. <bean id="dependency"class="com.apress.prospring2.ch04.bpp.Dependency"/>
  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. <bean id="bpp2"class="com.apress.prospring2.ch04.bpp.TimestampingBeanPostProcessor"/>
  14. <bean id="bpp3"class="com.apress.prospring2.ch04.bpp.TypedDependencyBeanPostProcessor"/>
  15. <bean id="bpp4"class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
  16. </beans>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值