【Spring源码系列】Bean生命周期-实例化前

2023-10-29

前言

在Bean的生命周期中,‘实例化前’操作是借助InstantiationAwareBeanPostProcessor接口实现的。

一、实例化前 - InstantiationAwareBeanPostProcessor介绍

BeanPostProcessor 提供的两个方法是:初始化前初始化后
很多类实现BeanPostProcessor,且基于BeanPostProcessor类做了些扩展,比如InstantiationAwareBeanPostProcessor类,在此基础上扩展了实例化前实例化后属性填充

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

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

}

InstantiationAwareBeanPostProcessor实例化前作用

实例化前操作只做一件事情:遍历bean执行postProcessBeforeInstantiation方法

InstantiationAwareBeanPostProcessor实例化前代码案例

代码实现InstantiationAwareBeanPostProcessor接口:

@Component
public class UserBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		// 声明:如果不指定对哪个bean进行处理,默认是对All的bean都会处理。
		if ("userService".equals(beanName)) {
			System.out.println("实例化前");
		}
		return null;
	}

}

实现InstantiationAwareBeanPostProcessor接口关键点声明:
1、 必须被@Component注解修饰。保证实现InstantiationAwareBeanPostProcessor接口的类可以被Spring扫描,扫描之后会被记录到BeanPostProcessorCache-instantiationAware属性集合中,目的是在创建每个bean的时候都会遍历instantiationAware集合执行postProcessBeforeInstantiation方法。
2、实现InstantiationAwareBeanPostProcessor接口且重写postProcessBeforeInstantiation方法

二、实例化前 - 源码分析

声明关键点

在讲源码之前呢,我们可以先增强几个知识点的概念。这些知识点在阅读’Spring-实例化前‘ 源码中起着关键作用。

1、实例化前操作只做一件事情:遍历bean执行postProcessBeforeInstantiation方法
2、Spring规定每一个BeanDefinition会执行‘实例化前’方法
3、如果实例化前返回一个不为null的对象,下一步则直接到初始化后。postProcessBeforeInstantiation方法如果返回一个不为null的对象,表示不需要Spring来实例化了,并且后续的Spring依赖注入也不会进行了,会跳过一些步骤,直接执行初始化后这一步。
4、AbstractBeanFactory$BeanPostProcessorCache类的instantiationAware集合在‘初始化前’就已经有值(**Spring容器启动的时候赋值的**)。不仅仅是instantiationAware,其余三个集合在执行‘初始化前’都已经被赋值。

static class BeanPostProcessorCache {

		/**
		 * 下面四个均是BeanPostProcessor的子类;
		 *
		 */
		final List<InstantiationAwareBeanPostProcessor> instantiationAware = new ArrayList<>();

		final List<SmartInstantiationAwareBeanPostProcessor> smartInstantiationAware = new ArrayList<>();

		final List<DestructionAwareBeanPostProcessor> destructionAware = new ArrayList<>();

		final List<MergedBeanDefinitionPostProcessor> mergedDefinition = new ArrayList<>();
	}

源代码解读

我们先找到Spring调用‘实例化前’的具体代码位置,‘实例化前’栈调用轨迹如下:
在这里插入图片描述org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[]):

// 实例化前
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation:

	@Nullable
	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.
			// synthetic表示合成,如果某些Bean式合成的,那么则不会经过BeanPostProcessor的处理
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					// 真正调用'实例化前'方法的地方。
					// 此处会获取postProcessBeforeInstantiation返回的对象,如果对象不为null则直接执行'初始化后'。
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation:

	@Nullable
	protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
		// getBeanPostProcessorCache()返回BeanPostProcessorCache对象,该对象的四个集合属性在执行'实例化前'就已经有值
		for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
			// 调用'实例化前-方法'
			Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
			if (result != null) {
				return result;
			}
		}
		return null;
	}

org.springframework.beans.factory.support.AbstractBeanFactory#getBeanPostProcessorCache:

BeanPostProcessorCache getBeanPostProcessorCache() {
		// '初始化前'调用之前,beanPostProcessorCache就已经有值
		BeanPostProcessorCache bpCache = this.beanPostProcessorCache;
		if (bpCache == null) {
			bpCache = new BeanPostProcessorCache();
			for (BeanPostProcessor bp : this.beanPostProcessors) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					bpCache.instantiationAware.add((InstantiationAwareBeanPostProcessor) bp);
					if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
						bpCache.smartInstantiationAware.add((SmartInstantiationAwareBeanPostProcessor) bp);
					}
				}
				if (bp instanceof DestructionAwareBeanPostProcessor) {
					bpCache.destructionAware.add((DestructionAwareBeanPostProcessor) bp);
				}
				if (bp instanceof MergedBeanDefinitionPostProcessor) {
					bpCache.mergedDefinition.add((MergedBeanDefinitionPostProcessor) bp);
				}
			}
			this.beanPostProcessorCache = bpCache;
		}
		return bpCache;
	}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Spring源码系列】Bean生命周期-实例化前 的相关文章

随机推荐

  • burpsuite插件自动识别图片验证码暴力破解

    burpsuite插件自动识别验证码暴力破解 1 准备工具 2 工具配置 2 1 burp导入captcha killer modified 0 14 jar 2 1 1 先生成jar包 2 1 2 再将jar包导入burp 2 2 kal
  • linux %s替换命令,linux vi 替换命令

    linux vi 替换命令 发布时间 2010 10 22 16 34 53 作者 佚名 我要评论 久了没用vi 命令都忘了 到网上找了些 记录下 以下内容出自网络 来源已经不详 vi vim 中可以使用 s 命令来替换字符串 以前只会使用
  • 高效程序员工作法(八)

    目录 前言 一 如何做好验收测试 一句话总结 二 你的代码是怎么变混乱的 一句话总结 三 总是在MVC分层架构 但你真的理解分层么 一句话总结 四 为什么总有人觉得5万块钱可以做一个淘宝 一句话总结 五 先做好DDD再谈微服务吧 那只是一种
  • CTFshow-pwn入门-前置基础pwn29-pwn31

    什么是PIE 由于ASLR是一种操作系统层面的技术 而二进制程序本身是不支持随机化加载的 便出现了一些绕过方法 例如ret2plt GOT劫持 地址爆破等 于是 人们于2003年引入了位置无关可执行文件 Position Independe
  • TMDS协议

    1 概述 1 1 连接结构 图1 TMDS连接结构 数据流中包含了像素和控制数据 发送器在任何给定的输入时钟周期 到底是编码像素数据还是控制数据取决于数据使能信号DE DE有效时 指示像素数据要被发送 注意 当发送像素数据的时候 忽略控制数
  • echarts中的饼状图设置颜色

    第一种方式 color FE8463 red green 第二种方式 itemStyle normal color function params 自定义颜色 var colorList FE8463 red green return co
  • windows2008服务器维护,Windows Server 2008R2 & windows server 2012 R2

    PAGE TITLEWindows Server 2008R2 windows server 2012 R2 windows服务器维护 86988 net contacts DESCRIPTIONMd5 file get DT ROOT l
  • C++中cout和cerr的区别

    标准IO库定义的其中3个IO对象 一个istream类型对象 cin 两个ostream对象 cout cerr cin 读取标准输入的istream对象 对应于标准输入流 关联到标准输入设备 通常为键盘 用来读取用户在终端上的输入内容 通
  • 2021-03-26

    爬虫笔记1 爬虫基础 1 爬虫的特点介绍 1 知识点碎片化 面对不同的网站 每个网站都有每个网站的特点 根据不同网站采取不同的技术和手段 2 学习难度在于要与网站的运维人员和维护人员进行搏斗 网站的网爬是不断升级 3 学习特点 爬虫的阶段课
  • 网络编程02

    网络通信 底层遵循TCP IP协议 在系统中以socket接口方式呈现 基于TCP协议的网络通信模型 服务端 客户端 创建socket对象 创建socket对象 准备通信地址 本机ip 端口号 准备通信地址 目标公网ip 端口号 绑定soc
  • UOS桌面版配置远程访问

    UOS桌面版配置远程访问 一 SSH SFTP 二 VNC 三 x11vnc service 一 SSH SFTP 安装SSH sudo apt update sudo apt install ssh 开启SFTP vi etc ssh s
  • 单次交换找字典序最小字符串

    题目要求 给一个字符串s 你可以至多选择两个不同位置的字符进行交换 可以不交换 问所有可能中字典序最小的串 输入 aaazbcdeadcd 输出 aaaabcdezdcd 题目解析 字典序最小 即与当前字符串相比最小的字符串 那么只需要找到
  • 【数据压缩】Exp01.彩色空间转换——YUV2RGB

    一 基本原理 这次的实验是将yuv格式的图像转换为rgb格式 两种彩色空间互相转换的公式如下 1 RGB转YUV Y 0 2990 R 0 5870 G 0 1140 B U 0 1684 R 0 3316 G 0 5 B V 0 5 R
  • css复习中常见的问题

    1 如果想让图片位于文字之后显示 即文字占前边 如下代码所示 img src dog jpg alt p 保护动物 人人有责 p 注意 由于在上述例子img标签元素设置了z index属性 即显示元素相对应的优先级 值 1即表示优先级滞后一
  • 虚拟机服务器的好处,vmware虚拟机的作用

    虚拟机不仅仅应用于学习与实验中 还可以直接应用于现实 使用VMware GSX Server或VMware ESX Server Microsoft Virtual Server 可以在一台高性能的服务器上同时运行多台虚拟机服务器 每台虚拟
  • kind & kubernetes 集群内如何通过 helm 部署定制化 Prometheus-Operator?

    文章目录 1 Prometheus 简介 2 Prometheus 优势 3 Prometheus 架构图 4 Prometheus Operator 简介 5 Prometheus Operator 架构图 6 环境准备 7 Kind 部
  • 优雅演进:探索低代码与全栈的完美结合

    前情提要 本章节是番外篇的低代码平台的相关知识 接下来我们即将进入一个全新的空间 对代码有一个全新的视角 以下的内容一定会让你对低代码平台有一个颠覆性的认识哦 以下内容干货满满 跟上步伐吧 作者介绍 作者 热爱编程不起眼的小人物 作者的Gi
  • sbt配置国内镜像

    操作环境 win10 从官网下载sbt的windows安装包 安装成功后 进入安装目录的 conf 文件夹 编辑sbtconfig txt 增加下面两行代码 Dsbt global base C Sbt sbt Dsbt repositor
  • 智能安全 - 学习资源

    Security Data Science Learning Resources
  • 【Spring源码系列】Bean生命周期-实例化前

    这里写目录标题 前言 一 实例化前 InstantiationAwareBeanPostProcessor介绍 InstantiationAwareBeanPostProcessor实例化前作用 InstantiationAwareBean