Spring BeanPostProcessor接口 (在Spring实例化bean的前后执行一些附加操作) .
2013-01-30 15:56
666 查看
在Spring实例化bean的前后执行一些附加操作。
有时,你会发现需要立刻在Spring实例化一个bean的前后执行一些附件操作。这些操作可以简单到修改一个bean,也可以复杂到返回一个完全不同的对象。
BeanPostProcessor接口包含两个method:
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());
}
}
配置:
view
plaincopy
to clipboardprint?
<?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>
调用:
view
plaincopy
to clipboardprint?
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的一个字段数据)
(例子的实现是像上面的例子一样,自己定义一个时间注解的实现)
view
plaincopy
to clipboardprint?
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
{
}
view
plaincopy
to clipboardprint?
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并为他们注解了日志字段设置当前日期:
view
plaincopy
to clipboardprint?
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;
}
}
配置文件:
view
plaincopy
to clipboardprint?
<?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>
调用:
view
plaincopy
to clipboardprint?
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。
view
plaincopy
to clipboardprint?
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的类型:
view
plaincopy
to clipboardprint?
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;
}
}
配置:
view
plaincopy
to clipboardprint?
<?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>
有时,你会发现需要立刻在Spring实例化一个bean的前后执行一些附件操作。这些操作可以简单到修改一个bean,也可以复杂到返回一个完全不同的对象。
BeanPostProcessor接口包含两个method:
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());
}
}
配置:
view
plaincopy
to clipboardprint?
<?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>
调用:
view
plaincopy
to clipboardprint?
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的一个字段数据)
(例子的实现是像上面的例子一样,自己定义一个时间注解的实现)
view
plaincopy
to clipboardprint?
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
{
}
view
plaincopy
to clipboardprint?
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并为他们注解了日志字段设置当前日期:
view
plaincopy
to clipboardprint?
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;
}
}
配置文件:
view
plaincopy
to clipboardprint?
<?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>
调用:
view
plaincopy
to clipboardprint?
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。
view
plaincopy
to clipboardprint?
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的类型:
view
plaincopy
to clipboardprint?
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;
}
}
配置:
view
plaincopy
to clipboardprint?
<?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>
相关文章推荐
- Spring源码分析之BeanPostProcessor接口和BeanFactoryPostProcessor接口方法不执行原因分析
- Spring源码分析之BeanPostProcessor接口和BeanFactoryPostProcessor接口方法不执行原因分析
- Spring BeanPostProcessor类 (在Spring实例化bean的前后执行一些附加操作)
- 关于Spring的Aware接口和后置处理器接口(BeanPostProcessor和BeanFactoryPostProcessor)的一些想法
- spring实例化一个bean的前后执行一些附件操作
- Spring BeanPostProcessor接口使用详解
- Spring 的 BeanPostProcessor接口实现
- Spring 的 BeanPostProcessor接口实现
- Spring BeanPostProcessor执行时机和Bean的初始化时机总结
- spring BeanPostProcessor接口
- Spring中BeanPostProcessor与InitializingBean接口的关系与应用
- Spring的BeanFactoryPostProcessor和BeanPostProcessor接口的区别
- Spring 的 BeanPostProcessor接口实现
- Spring 的 BeanPostProcessor接口实现
- 【spring源码分析】BeanDefinitionRegistryPostProcessor接口可自定义bean加入IOC
- Spring 的 BeanPostProcessor接口实现
- 【Spring源码分析】非懒加载的单例Bean初始化前后的一些操作
- Spring 的 BeanPostProcessor接口实现
- spring中InitializingBean,DisposableBean,BeanPostProcessor接口例子
- Spring 的 BeanPostProcessor接口实现