Spring IOC源码:registerBeanPostProcessors 详解

news2025/1/17 6:16:22

前言

上篇文章介绍了后置处理器BeanFactoryPostProcessor的注册、实例化及执行操作,这节介绍一下另外一个后置处理器BeanPostProcessor。前者是针对BeanFactory工厂对象进行增上改查操作,在bean实例化之前,我们可以修改其定义。后者是对实例化后的初始化环节前后对实例对象进行操作。

正文

进入refresh中的registerBeanPostProcessors(beanFactory)方法。该方法会将beanFactory工厂中所有BeanPostProcessor类型的BeanDefinition定义信息进行实例化注册,以便在bean的初始化环节中调用。

	protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
	}

PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this),见方法1详解

方法1:registerBeanPostProcessors

public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
		//从BeanFactory工厂中获取BeanPostProcessor的实现类beanName
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		//定义目标长度
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		//添加BeanPostProcessorChecker到beanFactory工厂中的beanPostProcessors集合中
		//这是个内部类,用来检查是否在bean的创建过程中,经过了所有本来应经过的后置处理器
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		//实现了PriorityOrdered接口的后置处理器集合
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		//内部的后置处理器集合
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		//实现了Ordered接口的后置处理器集合
		List<String> orderedPostProcessorNames = new ArrayList<>();
		//普通后置处理器集合
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				//实例化,获取对象
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				//	内部类型
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			//Ordered类型
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		//对集合中的后置处理器进行排序
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		//加入到工厂集合中
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		//将上述归类好的后置处理器进行实例化,并筛选出内部后置处理器
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		//排序
		sortPostProcessors(orderedPostProcessors, beanFactory);
		//注册添加到集合中
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// 处理普通的后置处理器
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		//注册添加到集合中
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// 最后对所有的内部后置处理器进行排序,注册处理
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		//移除之前添加的ApplicationListenerDetector,将其放到最后端
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

sortPostProcessors(priorityOrderedPostProcessors, beanFactory),方法我们在上篇文章中讲解《invokeBeanFactoryPostProcessors》中方法6

registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors),见方法2详解

beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)):

之前在refresh中的方法prepareBeanFactory添加过ApplicationListenerDetector,这里主要是排序,将该类型的后置处理器移到最后面来。

方法2:registerBeanPostProcessors

	private static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {

		for (BeanPostProcessor postProcessor : postProcessors) {
			beanFactory.addBeanPostProcessor(postProcessor);
		}
	}
	public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
		Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
		// 如果之前容器中存在该对象,则移除
		this.beanPostProcessors.remove(beanPostProcessor);
		// 如果是InstantiationAwareBeanPostProcessor类型的后置处理器,则标识为已注册
		if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
			this.hasInstantiationAwareBeanPostProcessors = true;
		}
		// 如果是DestructionAwareBeanPostProcessor类型的后置处理器,则标识为已注册
		if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
			this.hasDestructionAwareBeanPostProcessors = true;
		}
		// 添加到集合末尾
		this.beanPostProcessors.add(beanPostProcessor);
	}

自定义

我们知道BeanPostProcessor实现类会在bean实例化后,初始化环节中进行调用,那我们如何自定义一个BeanPostProcessor 实现类并注册到工厂中呢?上篇文章我们演示了如何自定义BeanFactoryPostProcessor,其操作方法也是类型的;

1、自定义BeanPostProcessor

public class MyBeanPostProcessor implements BeanPostProcessor {
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("after:"+beanName);
		return null;
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("before:"+beanName);
		return null;
	}
}

2、自定义上下文子类

通过拓展接口postProcessBeanFactory我们可以拿到工厂对象,并对其注册。

public class MyClassPathApplicationContext extends ClassPathXmlApplicationContext {

	public MyClassPathApplicationContext(String path){
		super(path);
	}

	@Override
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		beanFactory.addBeanPostProcessor(new MyBeanPostProcessor());
	}

}

3、编写入口

public class PersonTest {
	public static void main(String[] args) {

		MyClassPathApplicationContext applicationContext=new MyClassPathApplicationContext("application-scan.xml");
		StudentDao zdcDomain = (StudentDao) applicationContext.getBean("studentDao");
		System.out.println(zdcDomain);
	}
}

在这里插入图片描述

总结

BeanPostProcessor和BeanFactoryPostProcessor都属于IOC后置处理器,只是两者操作的对象不一样,并且调用时间点也不一样;
BeanPostProcessor:在bean实例化后的初始化环节中进行调用,可以对实例化的bean对象进行操作。
BeanFactoryPostProcessor:在实例化前进行调用,可以修改bean的定义信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/18788.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电脑重装系统蓝屏是什么原因

​电脑蓝屏是由于系统故障、致命的系统错误或系统崩溃而导致的现象&#xff0c;要想修复电脑蓝屏&#xff0c;关键是找出原因所在。为此&#xff0c;下面小编就给大家整理电脑蓝屏是什么原因。 原因1、虚拟内存不足造成系统多任务运算错误&#xff1a; 虚拟内存是Windows系统所…

(免费分享)基于springboot健康运动-带论文

源码获取&#xff1a;关注文末gongzhonghao&#xff0c;输入013领取下载链接 ​开发工具&#xff1a;IDEA, mysql5.7 技术&#xff1a;springbootmybatis-plus 健康管理包括&#xff1a;健康体检、健康评估、健康促进和健康服务四大部分。具体来说健康管理就是由健康管理顾问…

13.4 GAS与攻击

目录1. 由GA砍出的第一刀2. 挥剑时的命中检测3. 完善&#xff1a;UI显示当前血量参考&#xff1a;1. 由GA砍出的第一刀 有了前面章节的经验&#xff0c;我们可以很容易创建一个专用于攻击的GA&#xff1a; 其中PlayMontageAndWait任务节点负责攻击动画及相应回调的绑定。 但是…

向毕业妥协系列之深度学习笔记(二)深层神经网络

目录 一.深层神经网络 二.前向和反向传播 三.深层网络中的前向传播 四.核对矩阵的维数 五.为什么使用深层表示 六.参数VS超参数 一.深层神经网络 就是好多层。 二.前向和反向传播 三.深层网络中的前向传播 四.核对矩阵的维数 略 五.为什么使用深层表示 我们都知道深度…

在淘宝开店后,如何发布宝贝?从哪发布?

近期&#xff0c;有几位在淘宝新开店的店主&#xff0c;来向我们咨询了一些问题&#xff0c;总结来说可以将问题归为一个&#xff1a;在淘宝开店后&#xff0c;怎样上传宝贝&#xff1f;从哪上传&#xff1f;下面&#xff0c;小编来给大家简单的说一下发布宝贝时要注意什么&…

AD域 - 自动为域颁发证书

自动为域用户颁发数字证书 ———————————— 进入CA证书颁发机构 在“证书颁发机构”窗口中,鼠标右键点击“证书模板”,在弹出的快捷菜单中点击“管理” 在“证书模板控制台”窗口中,鼠标右键点击右侧列表中的“用户”,在弹出的快捷菜单中点击“复制模板

【Redis】Redis数据库的实现原理

在之前的文章我们介绍过&#xff0c;Redis服务器在启动之初&#xff0c;会初始化RedisServer的实例&#xff0c;在这个实例中存在很多重要的属性结构&#xff0c;同理本篇博客中介绍的数据库实现原理也会和其中的某些属性相关&#xff0c;我们继续看一下吧。 1.服务器和客户端…

【设计模式】 - 创建者模式 - 原型模式

目录标题1. 原型模式1.1 概述1.2 结构1.3 实现1.4 浅克隆Demo1&#xff1a;基本类型Demo2&#xff1a;引用类型浅克隆总结&#xff1a;1.5 深克隆实现方式1&#xff1a;浅克隆嵌套1. Address类实现Cloneable接口&#xff0c;重写clone方法;2. 在Customer类的clone方法中调用Add…

[附源码]SSM计算机毕业设计智慧教室预约JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

2019年1+X 证书 Web 前端开发中级理论考试——易错题、陌生但又会考到的题目原题+答案

文章目录 &#x1f3af;关于1X标准 &#x1f3af;关于中级考点 ❗❗❗注意&#xff1a; 理论题题型包括单选题、多选题、判断题。 ❗注意&#xff1a;题目序号没有修改 ❗红色的选项才是正确答案 ❗如果题目后面没有红色的选项&#xff0c;那么括号里面的答案是正确的 …

Unity游戏Mod/插件制作教程01 - BepInEx的安装和使用

前言 本章节为没有使用过BepInEx的同学进行BepInEx的安装和使用方面的介绍&#xff0c;如果你之前已经使用过并了解如何使用&#xff0c;可以直接跳过本章节。 BepInEx下载 BepInEx的Github链接 https://github.com/BepInEx/BepInEx/releases 一共有3种版本&#xff0c;BepIn…

Hive环境搭建

3.1 Hive环境搭建 3.1.1 Hive引擎简介 Hive引擎包括&#xff1a;默认MR、tez、spark Hive on Spark&#xff1a;Hive既作为存储元数据又负责SQL的解析优化&#xff0c;语法是HQL语法&#xff0c;执行引擎变成了Spark&#xff0c;Spark负责采用RDD执行。 Spark on Hive : Hi…

人人开源后台项目maven构建(yyds)

人人开源后台项目maven构建(yyds) npm run serve 和 npm run dev 的区别在日常运行vue 项目中 在终端 运行命令有时用到 npm run serve 有时是 npm run dev。那么&#xff0c;什么时候用到 serve &#xff0c;什么时候用到 dev 呢&#xff1f; 他们的区别是什么&#xff1f;一…

【学习笔记】《Python深度学习》第四章:机器学习基础

文章目录1 机器学习的四个分支1.1 监督学习1.2 无监督学习1.3 自监督学习1.4 强化学习2 评估机器学习模型2.1 训练集、验证集和测试集2.2 注意事项3 数据预处理、特征工程和特征学习3.1 神经网络的数据预处理3.2 特征工程4 过拟合与欠拟合4.1 减小网络大小4.2 添加权重正则化4.…

postgresql安装配置和基本操作

1.安装 linux上安装 最好是centos7.6或者7.8&#xff0c; 参考官网 PGSQL的官方地址&#xff1a;PostgreSQL: The worlds most advanced open source database PGSQL的国内社区&#xff1a;PostgreSQL中文社区:: 世界上功能最强大的开源数据库... 点击download PostgreSQ…

【Struts2】二_Struts2参数映射、核心配置文件struts.xml中的标签与属性的使用

文章目录Struts2一、参数映射&#xff1a;▶传递基本数据类型&#xff1a;▶传递对象二、核心配置文件struts.xml&#xff1a;2.1、constant标签2.2、package标签2.3、action标签三、Action配置&#xff1a;3.1、Action简介&#xff1a;3.2、继承ActionSupport类&#xff1a;3.…

JAVA初阶——继承和多态

目录 一、继承 1、定义&#xff1a; 2、用法&#xff1a; 3、使用从父类继承的成员 &#xff08;1&#xff09;、子类使用从父类继承的成员变量 &#xff08;2&#xff09;、子类使用从父类继承的成员方法 4、super &#xff08;1&#xff09;、定义&#xff1a; 5、子…

ID3算法

目录 ID3算法 例子 ID算法总结 ID3算法 ID3算法是在每个结点处选取能获得最高信息增益的分支属性进行分裂 在每个决策结点处划分分支、选取分支属性的目的是将整个决策树的样本纯度提升 衡量样本集合纯度的指标则是熵&#xff1b; 举例来说&#xff0c;如果有一个大小为10的…

被裁后,狂刷607页JUC源码分析笔记,立马拿蚂蚁offer

前言 可能大家最近&#xff0c;在公众号&#xff0c;或者各大自媒体平台&#xff0c;都能够刷到&#xff0c;因为疫情美国经济面临结构性衰退&#xff0c;美联储疯狂印钞导致世界性经济波动&#xff0c;导致国际环境不是很好&#xff0c;也间接影响到了中国&#xff0c;中国也…

跟艾文学编程《Python基础》(2)Python 容器

作者&#xff1a; 艾文&#xff0c;计算机硕士学位&#xff0c;企业内训讲师和金牌面试官&#xff0c;公司资深算法专家&#xff0c;现就职BAT一线大厂。 邮箱&#xff1a; 1121025745qq.com 博客&#xff1a;https://wenjie.blog.csdn.net/ 内容&#xff1a;跟艾文学编程《Pyt…