Sping源码(八)—registerBeanPostProcessors

序言

之前我们用大量的篇幅介绍过invokeBeanFactoryPostProcessors()方法的执行流程。
invokeBeanFactoryPostProcessors的主要逻辑就是遍历执行实现了BeanDefinitionRegistryPostProcesso类(主要是针对BeanDefinition的操作)和BeanFactoryPostProcessor(主要针对BeanFacroty的操作)
我们这篇文章里要介绍的registerBeanPostProcessors()方法 和 invokeBeanFactoryPostProcessors()方法类似,作用对象是Bean,用于在 Spring 容器实例化、配置和初始化 bean 的过程中提供自定义的扩展点。

源码

获取系统中实现BeanPostProcessor的类并进行分类,添加到BeanFacroty中。处理逻辑和BeanPosrProcessor基本相似。

	public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {//获取所有实现了BeanPostProcessor类的BeanNameString[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);// Register BeanPostProcessorChecker that logs an info message when// a bean is created during BeanPostProcessor instantiation, i.e. when// a bean is not eligible for getting processed by all BeanPostProcessors.//这里的 +1,应该是为了为下方的 new BeanPostProcessorChecker 留个位置//创建的BeanPostProcessorChecker是用来int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));// Separate between BeanPostProcessors that implement PriorityOrdered,// Ordered, and the rest.//用来存放实现riorityOrdered的BeanPostProcessorList<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();//用来存放实现MergedBeanDefinitionPostProcessor的BeanPostProcessorList<BeanPostProcessor> internalPostProcessors = new ArrayList<>();//用来存放实现Ordered的BeanPostProcessorList<String> orderedPostProcessorNames = new ArrayList<>();//用来存放没有实现排序接口的BeanPostProcessorList<String> nonOrderedPostProcessorNames = new ArrayList<>();//遍历获取所有的BeanPostProcessorfor (String ppName : postProcessorNames) {//判断是否实现了PriorityOrdered接口if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {//获取BeanPostProcessorBeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);priorityOrderedPostProcessors.add(pp);//判断是否实现了MergedBeanDefinitionPostProcessor接口if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}//如果实现了Ordered接口,则添加到orderedPostProcessorNames中else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}else {//否则就是没有实现排序接口的类nonOrderedPostProcessorNames.add(ppName);}}// First, register the BeanPostProcessors that implement PriorityOrdered.//根据优先级进行排序sortPostProcessors(priorityOrderedPostProcessors, beanFactory);//注册(循环添加到BeanFactory的beanPostProcessors集合中)实现priorityOrder接口的BeanPostProcessorregisterBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);// Next, register the BeanPostProcessors that implement Ordered.//注册(循环添加到BeanFactory的beanPostProcessors集合中)实现Ordered接口的BeanPostProcessorList<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);// Now, register all regular BeanPostProcessors.//最后注册(循环添加到BeanFactory的beanPostProcessors集合中)没有实现排序接口的BeanPostProcessorList<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);// Finally, re-register all internal BeanPostProcessors.//重新注册(循环添加到BeanFactory的beanPostProcessors集合中)实现MergedBeanDefinitionPostProcessor接口的BeanPostProcessorsortPostProcessors(internalPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, internalPostProcessors);// Re-register post-processor for detecting inner beans as ApplicationListeners,// moving it to the end of the processor chain (for picking up proxies etc).//注册ApplicationListenerDetector,// 其实refresh()主流程方法下的prepareBeanFactory(beanFactory)方法中已经向beanFactory中添加了ApplicationListenerDetector//这里是重新注册,保证ApplicationListenerDetector在beanPostProcessors集合的最后//目的是检测并管理应用程序上下文中的事件监听器。beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));

扩展

值得说的地方是Spirng提供了几个比较重要的BeanPostProcessor接口可以用来进行扩展。因为其与四个接口都继承自BeanPostProcessor所以BeanPostProcessor中的方法他们也都有。
在这里插入图片描述
挨个接口来看看里面都有什么。

BeanPostProcessor
bean的后置处理器接口,在依赖注入的初始化方法前后进行调用。

/*** bean的后置处理器接口,在依赖注入的初始化方法前后进行调用*/
public interface BeanPostProcessor {/*** 初始化方法调用前要进行的处理逻辑*/@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}/*** 在初始化方法指定后要进行的处理逻辑*/@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}}

InstantiationAwareBeanPostProcessor
新增了属性注入的方法。

/*** 继承自BeanPostProcessor,添加了实例化前,实例化后,属性注入后的处理方法*/
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {//省略BeanPostProcessor方法.../*** 当使用注解的时候,通过这个方法来完成属性的注入*/@Nullabledefault PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)throws BeansException {return null;}/*** 属性注入后执行的方法,在5.1版本被废弃*/@Deprecated@Nullabledefault PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;}}

SmartInstantiationAwareBeanPostProcessor
继承自InstantiationAwareBeanPostProcessor ,额外增加3个方法。

/*** 继承自InstantiationAwareBeanPostProcessor接口,增加了三个额外处理的方法,由spring内部使用**/
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {/*** 预测bean的类型,主要是在bean还没有创建前我们需要获取bean的类型**/@Nullabledefault Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {return null;}/*** 完成对构造函数的解析和推断*/@Nullabledefault Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)throws BeansException {return null;}/*** 解决循环依赖问题,通过此方法提前暴露一个合格的对象**/default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {return bean;}}

MergedBeanDefinitionPostProcessor
两个BeanDefinition合并时调用。

public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {/***spring通过此方法找出所有需要注入的字段,同时做缓存*/void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);/*** 用于在BeanDefinition被修改后,清除容器的缓存*/default void resetBeanDefinition(String beanName) {}
}

DestructionAwareBeanPostProcessor
判断Bean是否应该销毁和销毁时调用

public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {/*** 在bean被销毁前调用*/void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;/*** 判断是否要进行销毁,一般情况下都需要*/default boolean requiresDestruction(Object bean) {return true;}
}

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

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

相关文章

深入分析 Android Activity (五)

深入分析 Android Activity (五) 1. Activity 的进程和线程模型 在 Android 中&#xff0c;Activity 默认在主线程&#xff08;也称为 UI 线程&#xff09;中运行。理解进程和线程模型对于开发响应迅速且无阻塞的应用程序至关重要。 1.1 主线程与 UI 操作 所有 UI 操作必须…

干货 | 什么是单相感应电机控制器?一文带你看感应交流电机解决方案KP86202

单相感应电机控制器是一种用于控制单相感应电机运行的电子设备。单相感应电机是一种常见的电动机类型&#xff0c;广泛应用于家用电器、商业设备以及轻工制造等领域。 单相感应电机控制器通常包括电源模块、控制逻辑模块和功率输出模块。其主要功能是对单相感应电机进行启停、…

如何生成Github Badge徽章图标

如何生成徽章Badge 什么是徽章(Badge)生成小徽章shields网站开源项目的徽章lib版本徽章代码测试覆盖度开源协议Github workflow的徽章 开源代码实践效果py-enumjs-enumerate 什么是徽章(Badge) 在开源项目的README中&#xff0c;经常会见到一些徽章(Badge)小图标&#xff0c;如…

FastCopy

目录 背景: 简介&#xff1a; 原理: 下载地址: 工具的使用: 背景: 简介&#xff1a; FastCopy是一款速度非常快的拷贝软件&#xff0c;软件版本为5.7.1 Fastcopy是日本的最快的文件拷贝工具&#xff0c;磁盘间相互拷贝文件是司空见惯的事情&#xff0c;通常情况…

redis--redis Cluster

简介 解决了redis单机写入的瓶颈问题&#xff0c;即单机的redis写入性能受限于单机的内存大小、并发数量、网卡速率等因素无中心架构的redis cluster机制&#xff0c;在无中心的redis集群当中&#xff0c;其每个节点保存当前节点数据和整个集群状态,每个节点都和其他所有节点连…

【MySQL精通之路】InnoDB-INFORMATION_SCHEMA库Metrics表

1.介绍 INNODB_METRICS表提供了有关INNODB性能和资源相关计数器的信息。 INNODB_METRICS表列如下所示。 有关列描述&#xff0c;请参阅“INFORMATION_SCHEMA库INNODB_METRICS表”。 【MySQL精通之路】INFORMATION_SCHEMA库-INNODB_METRICS表-CSDN博客 mysql> SELECT * FRO…

好书推荐|MATLAB科技绘图与数据分析

提升你的数据洞察力&#xff0c;用于精确绘图和分析的高级MATLAB技术 MATLAB科技绘图与数据分析——jd 本书内容 《MATLAB科技绘图与数据分析》结合作者多年的数据分析与科研绘图经验&#xff0c;详细讲解MATLAB在科技图表制作与数据分析中的使用方法与技巧。全书分为3部分&a…

C语言 数组——数组的定义和初始化

目录 为什么使用数组(Array)? 一维数组的定义 一维数组的初始化 一维数组元素的访问 一维数组元素的赋值 数组的逻辑存储结构 数组的物理存储结构 二维数组的定义和初始化 为什么使用数组(Array)? 一维数组的定义 一维 数组的定义 int a[10]; 定义一个有 10 个 int 型元素的…

云WAF在应对新型网络攻击中的作用是什么?

云WAF&#xff08;Web Application Firewall&#xff09;在应对新型网络攻击中扮演着至关重要的角色。以下是云WAF的主要作用&#xff1a; 实时防御与智能分析 云WAF能够实时监测并分析网络流量&#xff0c;一旦发现潜在攻击行为立即进行阻断&#xff0c;有效防止各类Web应用层…

构建传统企业信息化数字化智能化技术架构:挑战与机遇

随着数字化和智能化技术的快速发展&#xff0c;传统企业在信息化转型过程中面临着前所未有的机遇和挑战。如何构建适应企业需求的信息化数字化智能化技术架构&#xff0c;成为企业发展的关键之一。本文将探讨传统企业信息化数字化智能化技术架构的设计与实践。 一、数字化转型的…

【缺失的第一个正数】leetcode,python

真是越做越觉得自己所学尚浅&#xff0c;&#xff0c; 啊&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f; 直接上石山代码&#xff1a;&#xff08;过不了一点&#xff09;。。。。。 class Solution:def firstMissingPositive(self…

SpringBoot发送邮箱

一、导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId> </dependency> 二、添加配置 application.yml文件 将username修改为自己的邮箱&#xff0c;password修改为…

SQL——DDL之数据表的操作

基础 # 每一列都要指定对应的类型 # 字符串&#xff1a;varchar(N) # 整数&#xff1a;int # 小数&#xff1a;double # 年月日&#xff1a;date # 年月日时分秒&#xff1a;datetime# 创建表 create table if not exists db_bigdata.student(stuid varchar(10),stuname varch…

[集群聊天服务器]----(四)MySQL数据库模块

上一节我们对网络模块和业务模块进行了解耦[集群聊天服务器]----(三)ChatService模块&#xff0c;解耦网络模块和业务模块&#xff0c;封装了回调函数。在项目中需要使用mysql数据库进行存储用户重要数据&#xff0c;并进行增删改查操作。&#xff0c;所以这一节我们对mysql的封…

Linux基础入门和帮助-第二篇

马哥教育 Linux SRE 学习笔记 用户登录信息查看命令 whoami: 显示当前登录有效用户 [rootrocky8 ~]$whoami rootwho: 系统当前所有的登录会话 [rootrocky8 ~]$who root pts/0 2024-05-24 12:55 (10.0.0.1)w: 系统当前所有的登录会话及所做的操作 [rootrocky8 ~]…

python对矩阵列进行操作

在Python中&#xff0c;可以使用NumPy库来对矩阵&#xff08;或称为矩阵、数组&#xff09;的列进行各种操作。以下是一些常见的列操作及其示例代码&#xff1a; import pandas as pd# 读取CSV文件 df pd.read_csv(output_file.csv, delimiter )# 对列进行求和 sum_columns …

WordPress 发布了独立的 SQLite 插件

之前 WordPress 在官方的 Performance Lab 插件实现 SQLite 模块&#xff0c;现在重构 SQLite 的实现&#xff0c;并且将其发布成一个独立的插件&#xff1a;SQLite Database Integration。 独立 SQLite 插件 最初的功能模块实现是基于 aaemnnosttv 的 wp-sqlite-db 插件修改实…

用ssh做跳板用周转服务器帮我们加速下载

假设有一台机器A&#xff0c;它从网站B下载东西很慢&#xff0c;但是有一台机器C&#xff0c;它从B下载比较快&#xff0c;它和A之间的速度也比较快&#xff0c;那么就可以在A发指令&#xff0c;通过ssh做跳板从C加速下载网站B的文件。 以下为示例命令&#xff1a; ssh 用户名…

【DevOps】Linux 下安装配置 Apache 服务器:打造你的专属 Web 平台

目录 一、准备工作 二、安装 Apache 三、启动和管理 Apache 四、验证安装 五、配置 Apache 5.1 修改网站根目录 5.2 配置虚拟主机 5.2.1 创建虚拟主机配置文件 5.2.2 创建网站目录 5.2.3 启用虚拟主机 5.2.4 重启 Apache 5.3 配置 HTTPS 5.3.1 安装 SSL 证书 5.3…

使用CyberRT写第一个代码, test ok

简介 计算框架是自动驾驶系统中的重中之重,也是整个系统得以高效稳定运行的基础。为了实时地完成感知、决策和执行,系统需要一系列的模块相互紧密配合,高效地执行任务流。由于各种原因,这些模块可能位于不同进程,也可能位于不同机器。这就要求计算框架中具有灵活的、高性…