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(即不做任何更改)。

相关推荐
聚美智数3 分钟前
常见疾病查询-疾病症状—疾病介绍-疾病大全-疾病治疗查询API接口介绍
android·java·数据库
慧都小妮子5 分钟前
Aspose.Words for JasperReports v26.6 发布,底层Java大升级
java·pdf·报表工具·aspose.words·文档转换·报表导出·jasperreports
白宇横流学长7 分钟前
基于SSM医院电子病历管理系统的设计与实现
java
观远数据7 分钟前
经营闭环的最后一公里:从看见问题到解决问题之间还差什么
java·开发语言·数据库
Java面试题总结12 分钟前
Go 语言大白话入门 6 - 判断与循环
开发语言·后端·golang
qq_4221525715 分钟前
PDF页面管理的几种实用方法:拆分、合并、删除指定页面
java·前端·pdf
hsg771 小时前
简述:Rust、GeoRust、自主研发GIS平台
开发语言·后端·rust
承渊政道1 小时前
飞算Java炫技赛:Java×Unity数字孪生园区平台的从零落地记录
java·开发语言·unity·技术分享·vibe coding·飞算javaai·飞算java ai炫技赛
wdfk_prog7 小时前
嵌入式面试真题第 10 题:高优化等级下共享状态可见性、内存模型与系统级同步设计
java·linux·开发语言·面试·职场和发展·架构·c
卓怡学长8 小时前
w255基于springboot仓库管理系统
java·数据库·spring boot·spring·intellij-idea