Spring系列 BeanPostProcessor

文章目录


本文源码基于spring-beans-5.3.31

参考:https://docs.spring.io/spring-framework/reference/core/beans/factory-extension.html#beans-factory-extension-bpp


BeanPostProcessor 是 Spring 框架中的一个接口,用于在 bean 实例化和初始化过程中进行一些回调处理,可以对Bean进行一些扩展或修改。

BeanPostProcessor

注册时机

AbstractApplicationContext#refresh里进行注册。此时所有Bean的配置信息都已解析并加载完毕

注册时并未区分BeanPostProcessor具体是什么类型

java 复制代码
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

AbstractBeanFactory维护了一个BeanPostProcessor列表,保存所有注册的 BeanPostProcessor

同时针对后期的使用提供了BeanPostProcessorCache这个类,用于缓存不同类型的BeanPostProcessor,从而进行不同的处理逻辑

通过懒加载策略进行初始化

java 复制代码
BeanPostProcessorCache getBeanPostProcessorCache() {
	synchronized (this.beanPostProcessors) {
		BeanPostProcessorCache bppCache = this.beanPostProcessorCache;
		if (bppCache == null) {
			bppCache = new BeanPostProcessorCache();
			// 区分不同的实现类型,放到对应的list集合中
			for (BeanPostProcessor bpp : this.beanPostProcessors) {
				if (bpp instanceof InstantiationAwareBeanPostProcessor) {
					bppCache.instantiationAware.add((InstantiationAwareBeanPostProcessor) bpp);
					if (bpp instanceof SmartInstantiationAwareBeanPostProcessor) {
						bppCache.smartInstantiationAware.add((SmartInstantiationAwareBeanPostProcessor) bpp);
					}
				}
				if (bpp instanceof DestructionAwareBeanPostProcessor) {
					bppCache.destructionAware.add((DestructionAwareBeanPostProcessor) bpp);
				}
				if (bpp instanceof MergedBeanDefinitionPostProcessor) {
					bppCache.mergedDefinition.add((MergedBeanDefinitionPostProcessor) bpp);
				}
			}
			this.beanPostProcessorCache = bppCache;
		}
		return bppCache;
	}
}

执行时机

BeanPostProcessor提供了Bean的生命周期的一些回调操作,所以它的执行是伴随着Bean的生命周期执行而执行的

InstantiationAwareBeanPostProcessor

org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor扩展了 BeanPostProcessor,用于在 bean 实例化和初始化过程中进行更细粒度的处理。

java 复制代码
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

	default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		return null;
	}

	default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		return true;
	}

	@Nullable
	default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
		return null;
	}

	@Deprecated
	@Nullable
	default PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
		return pvs;
	}
}

它提供了多个方法,下面是各个方法的作用

  1. postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
    在 bean 实例化之前调用。可以用于检查 bean 的元数据,决定是否需要实例化该 bean,或者返回一个替代的实例。可以返回一个替代的 bean 实例,或者返回 null 继续正常的实例化流程。
  1. postProcessAfterInstantiation(Object bean, String beanName)
    在 bean 实例化之后调用,可以用于逻辑处理,比如检查 bean 是否需要进行某些初始化操作。通常返回 true,表示允许继续进行属性填充。如果返回 false,则 Spring 将跳过属性的设置。
  1. postProcessProperties(PropertyValues pvs, Object bean, String beanName)
    在填充 bean 属性之前调用,用于处理 PropertyValues。可以修改属性值或条件性地填充属性。
    参数pvs 是待填充的属性值,bean 是当前的 bean 实例,beanName 是 bean 的名称。返回修改后的 PropertyValues,或者返回原始的 pvs。
  1. postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)

由于继承了BeanPostProcessor,所以postProcessBeforeInitialization(Object bean, String beanName)和postProcessAfterInitialization(Object bean, String beanName)这两个方法和BeanPostProcessor一致

SmartInstantiationAwareBeanPostProcessor

java 复制代码
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {

	@Nullable
	default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
		return null;
	}

	@Nullable
	default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
			throws BeansException {

		return null;
	}

	default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		return bean;
	}
}
  1. Class<?> predictBeanType(Class<?> beanClass, String beanName)
  1. Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
  1. Object getEarlyBeanReference(Object bean, String beanName)

在 bean 实例化后、初始化之前调用,允许返回早期的 bean 引用。这可以解决循环依赖问题,特别是在需要提前获取 bean 的情况下。返回早期的 bean 实例,或原始的 bean(即不做任何更改)。

相关推荐
老汉忒cpp5 分钟前
Redis string类型&&hash类型
java·redis·mybatis
智慧的牛6 分钟前
java往word中添加水印,往excel中添加图片
java·pdf·word·excel·水印
还算善良_16 分钟前
【设计模式】单例模式
java·单例模式·设计模式
终末圆22 分钟前
MyBatis—Plus 快速上手【后端 22】
java·开发语言·数据库·后端·sql·spring·mybatis
深情废杨杨24 分钟前
后端Java-SpringBoot整合MyBatisPlus步骤(超详细)
java·spring boot·spring
码代码的小农28 分钟前
SpringBoot自定义异常
java·spring boot·后端
岁岁岁平安32 分钟前
springboot实战学习(10)(ThreadLoacl优化获取用户详细信息接口)(重写拦截器afterCompletion()方法)
java·spring boot·后端·学习·threadlocal·jwt令牌
fareast_mzh36 分钟前
eMule allows you to optimize your queue and sharing efficiency
java·开发语言·数据库
聆听HJ1 小时前
java 解析excel (本地资源)
java·开发语言·excel
不拱地的猪1 小时前
想知道为什么有DICOM格式,YAML格式,XML格式,JSON格式吗?
xml·java·c++·opencv·json