BeanPostProcessor 源码分析

说明

  1. 本文基于 jdk 8, spring-framework 5.2.x 编写。
  2. @author JellyfishMIX - github / blog.jellyfishmix.com
  3. LICENSE GPL-2.0

BeanPostProcessor

什么是 BeanPostProcessor

BeanPostProcessor 是 spring-ioc 提供的重要的扩展接口,spring 内部的很多功能是通过 BeanPostProcessor 完成的(比如 AnnotationAwareAspectJAutoProxyCreator 的注入)。

BeanPostProcessor 接口提供了两个方法分别在 bean 初始化之前和之后进行调用。

  1. postProcessBeforeInitialization 方法,在 bean 初始化前调用,此时 bean 的属性注入已经完成,但还未调用 bean 实例的 init 方法进行初始化。
  2. postProcessAfterInitialization 方法,在 bean 初始化后调用,此时 bean 的属性注入已经完成,且已经通过 init 方法初始化完了。
public interface BeanPostProcessor {
	/**
	 * 在 bean 初始化前调用,此时 bean 的属性注入已经完成,但还未调用 bean 的 init 方法进行初始化
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 * 在 bean 初始化后调用,此时 bean 的属性注入已经完成,且已经通过 init 方法初始化完了
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
}

BeanPostProcessor 的调用时机

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean

  1. AbstractAutowireCapableBeanFactory#doCreateBean -> AbstractAutowireCapableBeanFactory#initializeBean 方法中,执行 invokeInitMethods 方法,调用 bean 的 init 方法及此阶段相关生命周期函数来初始化 bean。

  2. invokeInitMethods 方法执行之前和之后,调用了 BeanPostProcessor 的 postProcessBeforeInitialization 方法,postProcessAfterInitialization 方法。

	/**
	 * 初始化 bean
	 */
	protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		// invokeAwareMethods 方法,对特殊的 bean 进行处理: 实现了 Aware, BeanClassLoaderAware, BeanFactoryAware 等接口的 bean 的处理。
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			// 在初始化 bean 之前,调用 BeanPostProcessor#postProcessBeforeInitialization 方法,bean 的生命周期函数
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			// 调用 bean 的 init 方法及此阶段相关生命周期函数
			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()) {
			// 在初始化 bean 之后,调用 BeanPostProcessor#postProcessAfterInitialization 方法,bean 的生命周期函数
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		// 返回 wrappedBean
		return wrappedBean;
	}

	@Override
	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

	@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

BeanPostProcessor 的创建(注册)

spring-ioc 机制中,bean 的创建并非仅进行反射,还需要依赖于对应的 BeanDefinition 提供对应的信息。BeanDefinition 中不仅包含了 bean 的 class 文件信息,还包含了当前 bean 对应 spring-ioc 中的一些属性,比如 scope 作用域, lazyInit 是否懒加载, alias 别名等信息。

bean 的创建有两个步骤: bean 对应的 BeanDefinition 的创建,bean 实例的创建。BeanPostProcessor 本质也是 bean,也遵循这两个步骤。

  1. BeanPostProcessor 的 BeanDefinition 创建时机和普通 bean 的 BeanDefinition 没有区别,都是在 spring application 启动时执行 AbstractApplicationContext#refresh 方法时的 BeanFactoryPostProcessor 中完成(确切地说是 ConfigurationClassPostProcessor 中完成的)。
  2. 由于 BeanPostProcessor 参与了 bean 的创建过程,所以其创建一定在普通 bean 之前。BeanPostProcessor 的创建是在 spring application 启动时,AbstractApplicationContext#refresh 的地方。
    1. refresh 方法调用了 registerBeanPostProcessors 方法,从 beanFactory 中获取到所有 BeanPostProcessor 类型的beanName,通过 BeanFactory#getBean 方法获取到对应实例,进行排序后注册到 BeanFactory.beanPostProcessors 属性中。当需要使用 BeanPostProcessor 时,直接从 beanPostProcessors 中获取即可。
// BeanFactory

/** BeanPostProcessors to apply. */
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();

BeanPostProcessor 的种类

  1. BeanPostProcessor 在 spring 中的子类实现非常多,几十个是有的,例如:

    1. 比如 InstantiationAwareBeanPostProcessorAdapter: 作用在 spring 的 bean 加载过程中。

    2. AnnotationAwareAspectJAutoProxyCreator: bean 创建过程中的属性注入时起作用。

    3. AspectJAwareAdvisorAutoProxyCreator: AspectJ 的 aop 功能也需要 BeanPostProcessor 的特性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JellyfishMIX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值