BeanFactoryPostProcessor 介绍
BeanFactoryPostProcessor 可以 用于容器初始化还没有实例化Bean之前读取Bean的信息,并作出一些修改。
例如修改Bean的属性,修改Bean的scope等。
可以同时配置多个BeanFactoryPostProcessor,通过实现Ordered接口来决定执行顺序。
BeanFactoryPostProcessor
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
}
Ordered:
public interface Ordered {
int HIGHEST_PRECEDENCE = -2147483648;
int LOWEST_PRECEDENCE = 2147483647;
int getOrder();
}
BeanFactoryPostProcessor 使用案例
下面来写两个类,实现BeanFactoryPostProcessor和Ordered接口
BeanFactoryPostProcessorTest1:
public class BeanFactoryPostProcessorTest1 implements BeanFactoryPostProcessor ,Ordered {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("BeanFactoryPostProcessorTest1");
}
@Override
public int getOrder() {
return 2;
}
}
BeanFactoryPostProcessorTest2:
public class BeanFactoryPostProcessorTest2 implements BeanFactoryPostProcessor ,Ordered {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("BeanFactoryPostProcessorTest2");
}
@Override
public int getOrder() {
return 0;
}
}
bean.xml
<bean class="com.raycloud.dmj.data.utils.BeanFactoryPostProcessorTest1" />
<bean class="com.raycloud.dmj.data.utils.BeanFactoryPostProcessorTest2" />
main:
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
输出:
BeanFactoryPostProcessorTest2
BeanFactoryPostProcessorTest1
发现个有意思的现象,实现了BeanFactoryPostProcessor的类在容器初始化时就会被强制初始化,无论是否设置为多例,或者lazy_init。
通过源码了解BeanFactoryPostProcessor的执行时机
BeanFactoryPostProcessor在refresh()中的invokeBeanFactoryPostProcessors中执行,
整个过程是这样的:
1、先遍历执行已经在容器中注册的BeanFactoryPostProcessor
2、再找BeanDefinition中的BeanFactoryPostProcessor,通过getBean方法实例化,并且执行。
源码太多了,,不贴了
ps:
BeanFactoryPostProcessor 是容器相关的后置处理器,在实例化Bean之前执行一次。
BeanPostProcessor 介绍
BeanPostProcessor 与BeanFactoryProcessor是完全不一样的,BeanPostProcessor是Bean的后置处理器,在Bean的初始化方法[InitializingBean 以及init-method]前后执行。
注意:
可以配置多个BeanPostProcessor,执行的先后顺序依旧可以通过Ordered接口来实现。
public interface BeanPostProcessor {
//在Bean的初始化方法之前执行
Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException;
//在Bean的初始化方法之后执行
Object postProcessAfterInitialization(Object var1, String var2) throws BeansException;
}
BeanPostProcessor 使用
BeanPostProcessorTest1:
public class BeanPostProcessorTest1 implements BeanPostProcessor,Ordered {
@Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
System.out.println("BeanPostProcessorTest1 初始化之前");
return o;
}
@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
System.out.println("BeanPostProcessorTest1 初始化之后");
return o;
}
@Override
public int getOrder() {
return 1;
}
}
BeanPostProcessorTest2:
public class BeanPostProcessorTest2 implements BeanPostProcessor,Ordered {
@Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
System.out.println("BeanPostProcessorTest2 初始化之前");
return o;
}
@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
System.out.println("BeanPostProcessorTest2 初始化之后");
return o;
}
@Override
public int getOrder() {
return 0;
}
}
user:
public class User implements InitializingBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("setName");
this.name = name;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean 的 afterPropertiesSet");
}
public void initMethod(){
System.out.println("initMethod");
}
}
bean.xml:
<bean class="com.raycloud.dmj.data.utils.BeanPostProcessorTest1"/>
<bean class="com.raycloud.dmj.data.utils.BeanPostProcessorTest2"/>
<bean class="com.raycloud.dmj.data.utils.User" init-method="initMethod" >
<property name="name" value="ycf"/>
</bean>
main:
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
输出:
setName
BeanPostProcessorTest2 初始化之前
BeanPostProcessorTest1 初始化之前
InitializingBean 的 afterPropertiesSet
initMethod
BeanPostProcessorTest2 初始化之后
BeanPostProcessorTest1 初始化之后
通过源码了解BeanPostProcessor的注册和执行时机
BeanPostProcessor的注册时机:
refresh()中的registerBeanPostProcessors()。
主要关注
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
其实就是根据BeanPostProcessor的class去获取Bean的名称,然后之后根据名字和class去getBean注册到容器。
BeanPostProcessor的执行时机:
在获取Bean的doCreateBean的initializeBean中:
主要关注:
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean =
//初始化方法执行前
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean =
//初始化方法执行后
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
spring中,有内置的一些BeanPostProcessor实现类,例如:
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor:支持@Resource注解的注入
org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor:支持@Required注解的注入
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor:支持@Autowired注解的注入
org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor:支持@PersistenceUnit和@PersistenceContext注解的注入
org.springframework.context.support.ApplicationContextAwareProcessor:用来为bean注入ApplicationContext等容器对象
这些注解类的BeanPostProcessor,在spring配置文件中,可以通过这样的配置 <context:component-scan base-package="." /> ,自动进行注册。(spring通过ComponentScanBeanDefinitionParser类来解析该标签)
InstantiationAwareBeanPostProcessor介绍
InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口,因此他具有BeanPostProcessor的功能,可以在初始化方法执行前后进行一些操作。
除此之后还多了三个方法:
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
//bean实例化前
Object postProcessBeforeInstantiation(Class<?> var1, String var2) throws BeansException;
//bean实例化后
boolean postProcessAfterInstantiation(Object var1, String var2) throws BeansException;
//修改属性
PropertyValues postProcessPropertyValues(PropertyValues var1, PropertyDescriptor[] var2, Object var3, String var4) throws BeansException;
}
InstantiationAwareBeanPostProcessor使用
InstantiationAwareBeanPostProcessorTest :
public class InstantiationAwareBeanPostProcessorTest implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> aClass, String s) throws BeansException {
System.out.println("实例化之前");
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object o, String s) throws BeansException {
System.out.println("实例化之后");
return true;
}
@Override
public PropertyValues postProcessPropertyValues(PropertyValues propertyValues, PropertyDescriptor[] propertyDescriptors, Object o, String s) throws BeansException {
System.out.println("修改属性");
return propertyValues;
}
@Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
System.out.println("初始化之前");
return o;
}
@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
System.out.println("初始化之后");
return o;
}
}
user:
public class User implements InitializingBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("setName");
this.name = name;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean 的 afterPropertiesSet");
}
public void initMethod(){
System.out.println("initMethod");
}
}
bean.xml:
<bean class="com.raycloud.dmj.data.utils.InstantiationAwareBeanPostProcessorTest"/>
<bean class="com.raycloud.dmj.data.utils.User" init-method="initMethod" >
<property name="name" value="ycf"/>
</bean>
main:
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
输出:
实例化之前
实例化之后
修改属性
setName
初始化之前
InitializingBean 的 afterPropertiesSet
initMethod
初始化之后
通过源码了解InstantiationAwareBeanPostProcessor的执行时机
1、postProcessBeforeInstantiation 执行时机:
执行doCreateBean以前,createBean内:
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
postProcessBeforeInstantiation在Bean实例化之前执行,如果返回不会空,就替换Bean本身返回出去,有种代理模式的意思。
2、postProcessAfterInstantiation:
如果postProcessBeforeInstantiation返回不为空的bean,则立马执行postProcessAfterInstantiation。
否则正常初始化需要的Bean,在属性设置之前执行。
具体位置在populateBean里。
3、postProcessPropertyValues:
在postProcessAfterInstantiation返回true时才会执行,
是在真正设置属性之前对属性进行修改。
代码同样在populateBean里。
DestructionAwareBeanPostProcessor介绍
DestructionAwareBeanPostProcessor也是BeanPostProcessor的子接口,除了能在Bean的初始化方法执行前后做一些操作之外,还增加一个额外的方法。
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
//用于Bean销毁前做一些操作。
void postProcessBeforeDestruction(Object var1, String var2) throws BeansException;
}
DestructionAwareBeanPostProcessor使用
DestructionAwareBeanPostProcessorTest:
public class DestructionAwareBeanPostProcessorTest implements DestructionAwareBeanPostProcessor {
@Override
public void postProcessBeforeDestruction(Object o, String s) throws BeansException {
System.out.println("销毁前");
}
@Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
System.out.println("初始化之前");
return o;
}
@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
System.out.println("初始化之后");
return o;
}
}
user:
public class User implements InitializingBean,DisposableBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("setName");
this.name = name;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean 的 afterPropertiesSet");
}
public void initMethod(){
System.out.println("initMethod");
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean 的 destroy" );
}
public void destoryMethod(){
System.out.println("destoryMethod");
}
}
bean.xml:
<bean class="com.raycloud.dmj.data.utils.DestructionAwareBeanPostProcessorTest"/>
<bean class="com.raycloud.dmj.data.utils.User" init-method="initMethod" destroy-method="destoryMethod" >
<property name="name" value="ycf"/>
</bean>
main:
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
((ClassPathXmlApplicationContext) context).close();
输出:
setName
初始化之前
InitializingBean 的 afterPropertiesSet
initMethod
初始化之后
销毁前
DisposableBean 的 destroy
destoryMethod
通过案例可以看到DestructionAwareBeanPostProcessor的postProcessBeforeDestruction是在销毁方法执行前做的一些操作。
通过源码了解DestructionAwareBeanPostProcessor的执行时机
DestructionAwareBeanPostProcessor的postProcessBeforeDestruction在Bean destory的过程中执行,是在Bean的销毁方法前执行,具体位置是在
DisposableBeanAdapter的destory中,在开头就能看到,同时也是可以定义多个DestructionAwareBeanPostProcessor。
if (this.beanPostProcessors != null && !this.beanPostProcessors.isEmpty()) {
Iterator i$ = this.beanPostProcessors.iterator();
while(i$.hasNext()) {
DestructionAwareBeanPostProcessor processor = (DestructionAwareBeanPostProcessor)i$.next();
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}