Spring源码解析-10、BeanFactoryPostProcessor 与 BeanPostProcessor

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);
            }
        }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值