在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注解)
- publicclassSimpleBean {
- @PostConstruct
- publicvoidinitialize() {
- System.out.println("Initializing bean "+ getClass());
- }
- @PreDestroy
- publicvoidcleanUp() {
- 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>
调用:
- publicclassSimpleBeanDemo {
- publicstaticvoidmain(String[] args) {
- ConfigurableListableBeanFactory beanFactory =newXmlBeanFactory(
- newClassPathResource("/META-INF/spring/bpp-context.xml")
- );
- registerPostProcessor(beanFactory,"bpp");
- SimpleBean sb = (SimpleBean)beanFactory.getBean("simpleBean");
- System.out.println(sb);
- beanFactory.destroySingletons();
- }
- privatestaticvoidregisterPostProcessor(ConfigurableListableBeanFactory beanFactory, String beanName) {
- BeanPostProcessor bpp = (BeanPostProcessor) beanFactory.getBean(beanName);
- beanFactory.addBeanPostProcessor(bpp);
- }
- }
例子2:自己实现一个BeanPostProcessor接口(改变bean的一个字段数据)
(例子的实现是像上面的例子一样,自己定义一个时间注解的实现)
- packagecn.partner4java.beanpostprocessor;
- importjava.lang.annotation.ElementType;
- importjava.lang.annotation.Retention;
- importjava.lang.annotation.RetentionPolicy;
- importjava.lang.annotation.Target;
- /**
- * 声明一个运行时字段注解
- * @author partner4java
- *
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.FIELD)
- public@interfaceTimeStamp {
- }
- packagecn.partner4java.beanpostprocessor;
- importjava.util.Date;
- importjavax.annotation.PostConstruct;
- importjavax.annotation.PreDestroy;
- /**
- * 指定交给Spring管理的bean
- * @author partner4java
- *
- */
- publicclassSimpleBean {
- //自定义的注解
- @TimeStamp
- Date createDate;
- //spring中InitDestroyAnnotationBeanPostProcessor实现对bean init替代的注解
- @PostConstruct
- publicvoidinitialize(){
- System.out.println("initialize: "+ getClass());
- }
- //spring中InitDestroyAnnotationBeanPostProcessor实现对bean destory替代的注解
- @PreDestroy
- publicvoidcleanup(){
- System.out.println("cleanup: "+ getClass());
- }
- @Override
- publicString toString() {
- return"SimpleBean [createDate="+ createDate +"]";
- }
- }
编写一个BeanPostProcessor来检查每一个bean并为他们注解了日志字段设置当前日期:
- packagecn.partner4java.beanpostprocessor;
- importjava.lang.reflect.Field;
- importjava.util.Date;
- importorg.springframework.beans.BeansException;
- importorg.springframework.beans.factory.config.BeanPostProcessor;
- importorg.springframework.util.ReflectionUtils;
- /**
- * 编写一个BeanPostProcessor来检查每一个bean并为他们注解了日志字段设置当前日期
- * @author partner4java
- *
- */
- publicclassTimestampingBeanPostProcessorimplementsBeanPostProcessor {
- publicObject postProcessBeforeInitialization(finalObject bean, String beanName)
- throwsBeansException {
- ReflectionUtils.doWithFields(bean.getClass(),
- newReflectionUtils.FieldCallback() {
- publicvoiddoWith(Field field)throwsIllegalArgumentException,
- IllegalAccessException {
- field.set(bean,newDate());
- }
- },newReflectionUtils.FieldFilter() {
- publicbooleanmatches(Field field) {
- returnfield.getType() == Date.class&& field.getAnnotation(TimeStamp.class) !=null;
- }
- });
- returnbean;
- }
- publicObject postProcessAfterInitialization(Object bean, String beanName)
- throwsBeansException {
- returnbean;
- }
- }
配置文件:
- <?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>
调用:
- packagecn.partner4java.beanpostprocessor;
- importjavax.annotation.PreDestroy;
- importorg.springframework.beans.factory.config.BeanPostProcessor;
- importorg.springframework.beans.factory.config.ConfigurableListableBeanFactory;
- importorg.springframework.beans.factory.xml.XmlBeanFactory;
- importorg.springframework.core.io.ClassPathResource;
- publicclassSimpleBeanDemo {
- publicstaticvoidmain(String[] args) {
- ConfigurableListableBeanFactory beanFactory =newXmlBeanFactory(
- newClassPathResource("/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();
- }
- privatestaticvoidregisterPostProcessor(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。
- publicclassSimpleBean {
- @Timestamp
- Date creationDate;
- @Autowired
- String dependency;
- @PostConstruct
- publicvoidinitialize() {
- System.out.println("Initializing bean "+ getClass());
- }
- @PreDestroy
- publicvoidcleanUp() {
- System.out.println("Cleaning up bean "+ getClass());
- }
- @Override
- publicString toString() {
- return"Bean was created at "+this.creationDate +" with "+this.dependency;
- }
- }
我们修改bean的类型:
- publicclassTypedDependencyBeanPostProcessorextendsInstantiationAwareBeanPostProcessorAdapter {
- publicClass predictBeanType(Class beanClass, String beanName) {
- if(beanClass.equals(Dependency.class)) {
- returnString.class;
- }
- returnbeanClass;
- }
- publicObject postProcessBeforeInitialization(finalObject bean,finalString beanName)throwsBeansException {
- if(bean.getClass().equals(Dependency.class)) {
- return"Hello, world";
- }
- returnbean;
- }
- publicObject postProcessAfterInitialization(Object bean, String beanName)throwsBeansException {
- returnbean;
- }
- }
配置:
- <?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>