Spring源码分析衍生篇四:后处理器 BeanPostProcessor

一、前言

本文是 Spring源码分析:单例bean的获取 - createBean 的衍生文章。主要是因为本人菜鸡,在分析源码的过程中还有一些其他的内容不理解,故开设衍生篇来完善内容以学习。

二、BeanPostProcessor

所谓的 BeanPostProcessor 翻译过来就是Bean后处理器。实际上Spring还有一类后处理器BeanFactoryPostProcessor,源码还没看到这,暂不分析。

1. 什么是 BeanPostProcessor

BeanPostProcessor 是 Spring提供给我们的一个非常重要的扩展接口,并且Spring内部的很多功能也是通过 BeanPostProcessor 来完成的(目前看到最典型的就是 AnnotationAwareAspectJAutoProxyCreator 的 注入)。

2. BeanPostProcessor 的种类

BeanPostProcessor 在Spring 中的子类非常多(idea 显是有46个),比如

  • InstantiationAwareBeanPostProcessorAdapter : 在Spring 的bean加载过程中起了非常重要的作用
  • AnnotationAwareAspectJAutoProxyCreator : bean 创建过程中的 属性注入时起作用
  • AspectJAwareAdvisorAutoProxyCreator : Aspect 的 AOP 功能实现也全仰仗BeanPostProcessor 的特性。

3. BeanPostProcessor 的注册

BeanPostProcessor 的注册是在 AbstractApplicationContext#registerBeanPostProcessors 中完成的。在Spring 刚刚启动时候,会调用refresh() 方法,随机调用registerBeanPostProcessors 方法。 在这个方法中,Spring 将各处的BeanPostProcessor 的实现类 注册到 BeanFactory.beanPostProcessors 属性中,后面获取BeanPostProcessor 时直接通过该属性获取。

三、基本介绍

日常使用中,我们一般编写一个类来实现 BeanPostProcessor 或者 InstantiationAwareBeanPostProcessor 接口,根据每个方法的调用时机,来完成响应的工作。
下面介绍一下接口方法,这里通过 InstantiationAwareBeanPostProcessor 接口来介绍 。InstantiationAwareBeanPostProcessorBeanPostProcessor 的子接口,在 BeanPostProcessor 基础上又扩展了三个方法。

@Component
public class DemoPostProcesser implements InstantiationAwareBeanPostProcessor {
    
    

    //InstantiationAwareBeanPostProcessor 提供的方法, 在 Class<T> -> T 的转换过程中
    // 此时bean还没创建,可以通过这方法代替 Spring 容器创建的方法
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    
    
        System.out.println("DemoPostProcesser.postProcessBeforeInstantiation   ###  1");
        return null;
    }

    //InstantiationAwareBeanPostProcessor 提供的方法, 返回的值代表是否需要继续注入属性,
    // 如果返回true,则会调用postProcessProperties和postProcessPropertyValues 来注入属性
    // 此时bean已经创建,属性尚未注入
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    
    
        System.out.println("DemoPostProcesser.postProcessAfterInstantiation   ###  2");
        return true;
    }
    //InstantiationAwareBeanPostProcessor 提供的方法,可以在这个方法中进行bean属性的注入,Aop 就是在此方法中进行了代理的创建
    // 只有postProcessAfterInstantiation 返回true 时才会调用
    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
    
    
        System.out.println("DemoPostProcesser.postProcessProperties   ###  3");
        return pvs;
    }
    //InstantiationAwareBeanPostProcessor 提供的方法,可以在这个方法中进行bean属性的注入, 这个方法已经过时,使用postProcessProperties 代理
    // 只有postProcessAfterInstantiation 返回true 时 且 postProcessProperties 返回 null 时调用
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
    
    
        System.out.println("DemoPostProcesser.postProcessPropertyValues   ###  4");
        return pvs;
    }

    // BeanPostProcessor 提供的方法,在bean初始化前调用,这时候的bean大体已经创建完成了,在完成一些其他属性的注入
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    
        System.out.println("DemoPostProcesser.postProcessBeforeInitialization   ###  5");
        return bean;
    }
    // BeanPostProcessor 提供的方法,在bean初始化后调用,这时候的bean 已经创建完成了
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    
    
        System.out.println("DemoPostProcesser.postProcessAfterInitialization   ###  6");
        return bean;
    }
}

其调用顺序也和标注相同
在这里插入图片描述
注意:

这里可以看到 postProcessPropertyValues 方法并没有调用,因为对于一个 过时的方法 没必要必须要调用它,前面也提到 postProcessAfterInstantiation 返回true 并且 postProcessProperties 返回不为null 才会调用该方法,这里postProcessProperties 返回不为null ,所以不会调用postProcessPropertyValues 方法


四、源码中的调用场景

下面为了方便描述,进行一些简化写法,为了后面描述方便

BP : BeanPostProcessor
IBP : InstantiationAwareBeanPostProcessor
SBP : SmartInstantiationAwareBeanPostProcessor


其结构如下图:
在这里插入图片描述


这里就不具体贴出多少代码。简单解释一下调用场景

Spring 在启动过程中,会将所有实现了 BeanPostProcessor 接口的子类保存到 AbstractBeanFactory 中的 beanPostProcessors 集合中,如下:

private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();

在适当的时候(这个适当的时候就根据 每个接口方法定义的意义来判断), Spring会获取 所有的BeanPostProcessor 子类集合,即 beanPostProcessors ,经过类型过滤后,调用对应的方法。比如,就是对 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 方法的调用流程(其余方法的调用也类似):

	protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    
    
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
    
    
		// 因为只有 InstantiationAwareBeanPostProcessor  类型才有postProcessBeforeInstantiation 方法,所以这里要判断一下是不是 InstantiationAwareBeanPostProcessor   类型
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
    
    
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
    
    
					return result;
				}
			}
		}
		return null;
	}

1. InstantiationAwareBeanPostProcessor

下面来介绍在 Spring 创建流程中 每个方法的实际调用位置:

1.1. IBP.postProcessBeforeInstantiation

IBP.postProcessBeforeInstantiation 方法在 Bean 创建 之前调用,我所理解的目的是替换Spring 容器创建bean, 当 IBP.postProcessBeforeInstantiation 返回不为null时,则不会再通过Spring 创建bean,而是使用 IBP.postProcessBeforeInstantiation 返回的bean。

			...
			// 该方法中 调用了postProcessBeforeInstantiation 方法,并且可能调用 postProcessAfterInitialization 方法
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
    
    
				return bean;
			}
			...
			// 真正去创建bean
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			...

resolveBeforeInstantiation 方法内容如下,可以看到 当 applyBeanPostProcessorsBeforeInstantiation 方法(applyBeanPostProcessorsBeforeInstantiation 调用了 postProcessBeforeInstantiation 方法) 返回值不为 null,则会调用 postProcessAfterInstantiation 方法。因为这里bean返回不为null,则代表bean创建成功了,就会调用创建成功后的方法,即 postProcessAfterInstantiation

	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;
	}

这里需要注意,在 resolveBeforeInstantiation 方法中,当 bean != null 时 调用了 applyBeanPostProcessorsAfterInitialization 方法,即 BP.postProcessAfterInitialization 方法。这是因为如果 bean != null, 则说明 bean 的创建已经完成,那么这里则是最后调用bean 的后置处理的机会,即调用BP.postProcessAfterInitialization 方法的最后机会。

1.2. IBP.postProcessAfterInstantiation & IBP.postProcessProperties & IBP.postProcessPropertyValues

IBP.postProcessAfterInstantiationIBP.postProcessPropertiesIBP.postProcessPropertyValues 的调用场景只有一处,在AbstractAutowireCapableBeanFactory#populateBean 方法中,此时bean已经创建完成,正在进行属性注入。而 IBP.postProcessAfterInstantiation 的返回值决定是否继续注入

大致代码如下

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    
    
		...
		// 调用 postProcessAfterInstantiation 方法吗,如果返回false,直接return;
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    
    
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
    
    
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
    
    
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    
    
						return;
					}
				}
			}
		}

		... 
		if (hasInstAwareBpps) {
    
    
			if (pvs == null) {
    
    
				pvs = mbd.getPropertyValues();
			}
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
    
    
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
    
    
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					// 调用 postProcessProperties 注入属性
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
    
    
						if (filteredPds == null) {
    
    
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						// 调用 postProcessPropertyValues 注入属性
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
    
    
							return;
						}
					}
					pvs = pvsToUse;
				}
			}
		}
	...
	}

通过代码我们可以比较清楚的看到整体逻辑:

  1. IBP.postProcessAfterInstantiation 返回true,才会执行下面步骤
  2. 调用 IBP.postProcessProperties 注入属性,
  3. IBP.postProcessProperties 返回为null,才会执行下面步骤
  4. 调用 IBP.postProcessPropertyValues 注入属性

2. BeanPostProcessor

2.1. BP.postProcessBeforeInitialization

BP.postProcessBeforeInitialization 调用时机是bean已经创建完成,但是尚未初始化,即一些属性配置尚未完成(我看到的就一个 init-method 的配置)。使用场景也只有一处,即
AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition)

程序走到这里,代表 resolveBeforeInstantiation 方法 中的 IBP.postProcessBeforeInstantiation 并未代理 bean的创建,在这里则是由Spring 创建的bean的时候来调用。

代码如下,

	protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    
    
		....
		// 调用 BP.postProcessBeforeInitialization
		if (mbd == null || !mbd.isSynthetic()) {
    
    
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}
		// 初始化属性,貌似就初始化了 一个 init-method
		...
		if (mbd == null || !mbd.isSynthetic()) {
    
    
			// 调用 BP.postProcessAfterInitialization
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

2.2. BP.postProcessAfterInitialization

IBP.postProcessAfterInstantiation 的调用都被封装到 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization 方法中。
applyBeanPostProcessorsAfterInitialization 方法的调用

applyBeanPostProcessorsAfterInitialization 方法在下面三个方法中调用:

  • AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
  • AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition)
  • AbstractAutowireCapableBeanFactory#postProcessObjectFromFactoryBean

2.2.1 resolveBeforeInstantiation

resolveBeforeInstantiation 方法的调用有如下三处

  • AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[]) 这里的调用实际上就是上面讲的 IBP.postProcessBeforeInstantiation 的调用后续,所以这里不再重复

  • AbstractAutowireCapableBeanFactory#getSingletonFactoryBeanForTypeCheck

  • AbstractAutowireCapableBeanFactory#getNonSingletonFactoryBeanForTypeCheck


2.2.2 initializeBean

上面介绍 BP.postProcessBeforeInitialization 的时候已经说了,所以这里不再赘述


2.2.3 postProcessObjectFromFactoryBean

FactoryBeanRegistrySupport#getObjectFromFactoryBean 中调用,在从 FactoryBean 中获取 bean时调用,在此调用可以替换掉 FactoryBean 中的返回的bean。


3. SmartInstantiationAwareBeanPostProcessor

SmartInstantiationAwareBeanPostProcessor 在 IBP 之上又扩展了三个方法,不过我们一般不会使用,所以这里简单叙述一下SmartInstantiationAwareBeanPostProcessor 三个方法的作用

  • Class<?> predictBeanType(Class<?> beanClass, String beanName) : 在进行bean类型匹配时调用,返回值和期望值进行匹配。

  • Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) : 在 Spring 加载bean 的时候,判断是否需要通过构造注入时,如果返回的值不为空,则进行有参构造注入。

    	// determineConstructorsFromBeanPostProcessors 中调用了  determineCandidateConstructors 方法,如果ctors != null, 则进行有参构造autowireConstructor
    		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
    				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
          
          
    			return autowireConstructor(beanName, mbd, ctors, args);
    		}
    
  • Object getEarlyBeanReference(Object bean, String beanName) : 在 Spring 解决循环依赖时候使用,返回的值将作为ObjectFactory 的 保存的Object,用于循环依赖的提前暴露。

    		if (earlySingletonExposure) {
          
          
    			if (logger.isTraceEnabled()) {
          
          
    				logger.trace("Eagerly caching bean '" + beanName +
    						"' to allow for resolving potential circular references");
    			}
    			// getEarlyBeanReference 的返回值作为 ObjectFactory 的返回值保存到singletonFactories缓存中
    			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    		}
    

最后,附一张自己画的调用流程图,由于完全有本人自己阅读绘制,可能会出现些许纰漏,如果发现,麻烦指正,谢谢。
在这里插入图片描述


以上:内容部分参考
《Spring源码深度解析》
如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正

猜你喜欢

转载自blog.csdn.net/qq_36882793/article/details/106040809
今日推荐