Spring实例化源码解析之registerBeanPostProcessors(六)

BeanPostProcessors是Spring框架中的一个扩展机制,它允许开发人员在Spring容器实例化、配置和初始化Bean的过程中干预和定制化。BeanPostProcessor接口定义了两个方法:postProcessBeforeInitialization和postProcessAfterInitialization,分别在Bean初始化之前和之后被调用。

BeanPostProcessors的作用是在Bean的初始化过程中提供额外的处理逻辑。通过实现BeanPostProcessor接口并注册到Spring容器中,开发人员可以在Bean实例化后的早期和后期阶段对Bean进行修改、增强或执行其他自定义逻辑。这样可以实现很多功能,如属性注入、AOP代理、资源初始化等。

猜测

入口是在AbstractApplicationContext的refresh方法中,在方法中调用了registerBeanPostProcessors(beanFactory),从字面意思来说就是注册BeanPostProcessors,BeanPostProcessor具体做什么用的上面也有介绍,本章就分析一下这个注册做了哪些事情。

分析

老规矩,从入口的注释开始,这个方法就是实例化和注册所有的BeanPostProcessor,尊重期望的排序,如果有给出的话,这个方法必须在我们应用bean实力化之前被调用。

/*** Instantiate and register all BeanPostProcessor beans,* respecting explicit order if given.* <p>Must be called before any instantiation of application beans.*/
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

方法实际调用的是PostProcessorRegistrationDelegate类中的registerBeanPostProcessors方法,如果调用参数的详细入下截图所示:
请添加图片描述

PostProcessorRegistrationDelegate

这个类中的方法其实就是整个代码的核心,接下来我们继续用拆解的方式来进行分析,下面是其所有的代码块。

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {// WARNING: Although it may appear that the body of this method can be easily// refactored to avoid the use of multiple loops and multiple lists, the use// of multiple lists and multiple passes over the names of processors is// intentional. We must ensure that we honor the contracts for PriorityOrdered// and Ordered processors. Specifically, we must NOT cause processors to be// instantiated (via getBean() invocations) or registered in the ApplicationContext// in the wrong order.//// Before submitting a pull request (PR) to change this method, please review the// list of all declined PRs involving changes to PostProcessorRegistrationDelegate// to ensure that your proposal does not result in a breaking change:// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22String[] 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.int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));// Separate between BeanPostProcessors that implement PriorityOrdered,// Ordered, and the rest.List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();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);}}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}else {nonOrderedPostProcessorNames.add(ppName);}}// First, register the BeanPostProcessors that implement PriorityOrdered.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);// Now, register all regular BeanPostProcessors.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);// Finally, re-register all internal BeanPostProcessors.sortPostProcessors(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).beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

步骤一:

直接通过类型去获取所有的BeanPostProcessor的BeanNames,存在postProcessorNames数组中。

String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

步骤二:

注册一个名为BeanPostProcessorChecker的BeanPostProcessor,并将其添加到beanFactory中。

具体分析如下:

  1. 获取已注册的BeanPostProcessor数量:

    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount();
    ```
    这行代码获取已经注册到beanFactory的BeanPostProcessor的数量。
  2. 计算新的BeanPostProcessor的目标数量:

    beanProcessorTargetCount = beanProcessorTargetCount + 1 + postProcessorNames.length;
    ```
    在已有的BeanPostProcessor数量基础上,加上1(表示新注册的BeanPostProcessorChecker)以及postProcessorNames的长度(表示后续要注册的BeanPostProcessor的数量),计算出新的目标数量。
  3. 创建并注册BeanPostProcessorChecker:

    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
    ```
    创建一个名为BeanPostProcessorCheckerBeanPostProcessor实例,并将其添加到beanFactory中。BeanPostProcessorChecker是一个自定义的BeanPostProcessor,它在BeanPostProcessor实例化期间检查并记录信息。具体来说,当创建BeanPostProcessor期间创建了一个Bean(即一个Bean不符合所有BeanPostProcessor的处理条件)时,BeanPostProcessorChecker会记录一个信息日志。

步骤三:

对已注册的BeanPostProcessor进行分类,并按照优先级顺序注册到beanFactory中。

  1. 创建用于存储实现PriorityOrdered接口的BeanPostProcessor的列表:

    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    ```
    创建一个名为priorityOrderedPostProcessors的列表,用于存储实现了PriorityOrdered接口的BeanPostProcessor
  2. 创建用于存储内部BeanPostProcessor的列表:

    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
    ```
    创建一个名为internalPostProcessors的列表,用于存储内部的BeanPostProcessor
  3. 创建用于存储实现Ordered接口的BeanPostProcessor名称的列表:

    List<String> orderedPostProcessorNames = new ArrayList<>();
    ```
    创建一个名为orderedPostProcessorNames的列表,用于存储实现了Ordered接口的BeanPostProcessor的名称。
  4. 创建用于存储未实现Ordered接口的BeanPostProcessor名称的列表:

    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    ```
    创建一个名为nonOrderedPostProcessorNames的列表,用于存储未实现Ordered接口的BeanPostProcessor的名称。
  5. 遍历已注册的BeanPostProcessor名称列表,根据其类型进行分类:

    for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {// BeanPostProcessor实现了PriorityOrdered接口BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);priorityOrderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {// 内部的BeanPostProcessorinternalPostProcessors.add(pp);}}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {// BeanPostProcessor实现了Ordered接口orderedPostProcessorNames.add(ppName);}else {// 未实现Ordered接口的BeanPostProcessornonOrderedPostProcessorNames.add(ppName);}
    }
    ```
    遍历已注册的BeanPostProcessor名称列表postProcessorNames,根据名称对应的BeanPostProcessor的类型进行分类。如果BeanPostProcessor实现了PriorityOrdered接口,则将其添加到priorityOrderedPostProcessors列表中;如果是MergedBeanDefinitionPostProcessor的实例,则也添加到internalPostProcessors列表中;如果实现了Ordered接口,则将其名称添加到orderedPostProcessorNames列表中;否则,将其名称添加到nonOrderedPostProcessorNames列表中。
  6. 对实现PriorityOrdered接口的BeanPostProcessor进行排序:

    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    ```
    调用sortPostProcessors方法对priorityOrderedPostProcessors列表中的BeanPostProcessor进行排序,按照优先级顺序进行排序。
  7. 注册实现PriorityOrdered接口的BeanPostProcessor到beanFactory中:

    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
    ```
    调用registerBeanPostProcessors方法,将priorityOrderedPostProcessors列表中的BeanPostProcessor注册到beanFactory中。

步骤四:

实现了Ordered接口的BeanPostProcessor到beanFactory中。

  1. 创建用于存储实现Ordered接口的BeanPostProcessor的列表:

    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    ```
    创建一个名为orderedPostProcessors的列表,用于存储实现了Ordered接口的BeanPostProcessor
  2. 遍历实现了Ordered接口的BeanPostProcessor的名称列表,并将它们实例化并添加到orderedPostProcessors列表中:

    for (String ppName : orderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);orderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {// 内部的BeanPostProcessorinternalPostProcessors.add(pp);}
    }
    ```
    遍历实现了Ordered接口的BeanPostProcessor的名称列表orderedPostProcessorNames,通过beanFactory.getBean方法实例化每个BeanPostProcessor,并将其添加到orderedPostProcessors列表中。如果BeanPostProcessorMergedBeanDefinitionPostProcessor的实例,则也添加到internalPostProcessors列表中。
  3. 对实现Ordered接口的BeanPostProcessor进行排序:

    sortPostProcessors(orderedPostProcessors, beanFactory);
    ```
    调用sortPostProcessors方法对orderedPostProcessors列表中的BeanPostProcessor进行排序,按照Ordered接口的顺序进行排序。
  4. 注册实现Ordered接口的BeanPostProcessor到beanFactory中:

    registerBeanPostProcessors(beanFactory, orderedPostProcessors);
    ```
    调用registerBeanPostProcessors方法,将orderedPostProcessors列表中的BeanPostProcessor注册到beanFactory中。

步骤五:

注册剩余的未实现Ordered接口的BeanPostProcessor,并重新注册内部的BeanPostProcessor。

  1. 创建用于存储未实现Ordered接口的BeanPostProcessor的列表:

    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    ```
    创建一个名为nonOrderedPostProcessors的列表,用于存储未实现Ordered接口的BeanPostProcessor
  2. 遍历未实现Ordered接口的BeanPostProcessor的名称列表,并将它们实例化并添加到nonOrderedPostProcessors列表中:

    for (String ppName : nonOrderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);nonOrderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {// 内部的BeanPostProcessorinternalPostProcessors.add(pp);}
    }
    ```
    遍历未实现Ordered接口的BeanPostProcessor的名称列表nonOrderedPostProcessorNames,通过beanFactory.getBean方法实例化每个BeanPostProcessor,并将其添加到nonOrderedPostProcessors列表中。如果BeanPostProcessorMergedBeanDefinitionPostProcessor的实例,则也添加到internalPostProcessors列表中。
  3. 注册未实现Ordered接口的BeanPostProcessor到beanFactory中:

    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
    ```
    调用registerBeanPostProcessors方法,将nonOrderedPostProcessors列表中的BeanPostProcessor注册到beanFactory中。
  4. 对内部的BeanPostProcessor进行排序:

    sortPostProcessors(internalPostProcessors, beanFactory);
    ```
    调用sortPostProcessors方法对internalPostProcessors列表中的BeanPostProcessor进行排序。
  5. 重新注册内部的BeanPostProcessor到beanFactory中:

    registerBeanPostProcessors(beanFactory, internalPostProcessors);
    ```
    调用registerBeanPostProcessors方法,将internalPostProcessors列表中的BeanPostProcessor重新注册到beanFactory中。
  6. 重新注册用于检测内部Bean作为ApplicationListeners的后处理器:

    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    ```
    创建一个ApplicationListenerDetector的实例,并将其作为BeanPostProcessor添加到beanFactory中。这个后处理器用于检测内部Bean是否为ApplicationListeners,并将其移动到处理器链的末尾,以便在处理代理等情况时能够正确拾取内部Bean

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

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

相关文章

大模型 Decoder 的生成策略

本文将介绍以下内容&#xff1a; IntroductionGreedy Searchbeam searchSamplingTop-K SamplingTop-p (nucleus) sampling总结 一、Introduction 1、简介 近年来&#xff0c;由于在数百万个网页数据上训练的大型基于 Transformer 的语言模型的兴起&#xff0c;开放式语言生…

双重差分模型(DID)论文写作指南与操作手册

手册链接&#xff1a;双重差分模型&#xff08;DID&#xff09;论文写作指南与操作手册https://www.cctalk.com/m/group/90983583?xh_fshareuid60953990 简介&#xff1a; 当前&#xff0c;对于准应届生们来说&#xff0c;毕设季叠加就业季&#xff0c;写作时间显得十分宝贵…

EdgeView 4 for Mac:重新定义您的图像查看体验

您是否厌倦了那些功能繁杂、操作复杂的图像查看器&#xff1f;您是否渴望一款简单、快速且高效的工具&#xff0c;以便更轻松地浏览和管理您的图像库&#xff1f;如果答案是肯定的&#xff0c;那么EdgeView 4 for Mac将是您的理想之选&#xff01; EdgeView 4是一款专为Mac用户…

Spacewalk

Spacewalk Spacewalk是一种开源的系统管理工具&#xff0c;提供了集中管理多个Linux服务器的功能。以下是一些Spacewalk用例&#xff1a; Spacewalk是基于Substrate的parachains和Stellar之间的桥梁&#xff0c;可以实现与Stellar的资产转移。该拨款申请用于开发太空行走协议…

FFmpeg日志系统、文件与目录、操作目录

目录 FFmpeg日志系统 FFmpeg文件与目录操作 FFmpeg文件的删除与重命名 FFmpeg操作目录及list的实现 操作目录重要函数 操作目录重要结构体 FFmpeg日志系统 下面看一个简单的 demo。 #include <stdio.h> #include <libavutil/log.h>int main(int argc,char* …

讲讲项目里的仪表盘编辑器(四)分页卡和布局容器组件

讲讲两个经典布局组件的实现 ① 布局容器组件 配置面板是给用户配置布局容器背景颜色等属性。这里我们不需要关注 定义文件 规定了组件类的类型、标签、图标、默认布局属性、主文件等等。 // index.js import Container from ./container.vue; class ContainerControl extends…

ARMv8如何读取cache line中MESI 状态以及Tag信息(tag RAM dirty RAM)并以Cortex-A55示例

Cortex-A55 MESI 状态获取 一&#xff0c;系统寄存器以及读写指令二&#xff0c;Cortex-A55 Data cache的MESI信息获取&#xff08;AARCH 64&#xff09;2.1 将Set/way信息写入Data Cache Tag Read Operation Register2.2 读取Data Register 1和Data Register 0数据并解码 参考…

Linux嵌入式学习之Ubuntu入门(六)shell脚本详解

系列文章内容 Linux嵌入式学习之Ubuntu入门&#xff08;一&#xff09;基本命令、软件安装、文件结构、编辑器介绍 Linux嵌入式学习之Ubuntu入门&#xff08;二&#xff09;磁盘文件介绍及分区、格式化等 Linux嵌入式学习之Ubuntu入门&#xff08;三&#xff09;用户、用户组…

Java 基于 SpringBoot 的学生考勤系统

1 简介 本文讲解的是 Java基于 SpringBoot 的学生考勤系统。学生考勤管理系统能做到的不仅是大大简化管理员的信息管理工作&#xff0c;在提高学生考勤管理效率的同时还能缩减开支&#xff0c;更能在数字化的平面网络上将学生考勤管理最好的一面展示给客户和潜在客户&#xff…

swift加载h5页面空白

swift加载h5页面空白 problem 背景 xcode swift 项目&#xff0c;WebView方式加载h5页面本地h5地址是&#xff1a;http://localhost:5173/ 浏览器打开正常 Swift 加载h5&#xff1a; 百度官网 加载正常本地h5页面 加载空白&#xff0c;没有报错 override func viewDidLoad…

Netron【.pt转.torchscript模型展示】

Netron是一个模型的展示工具&#xff0c;它有网页版和app版&#xff1a; 网页版&#xff1a;Netron app版&#xff1a;GitHub - lutzroeder/netron: Visualizer for neural network, deep learning, and machine learning models 直接用网页版吧&#xff0c;还不用安装。 它可…

安装NodeJS并使用yarn下载前端依赖

文章目录 1、安装NodeJS1.1 下载NodeJS安装包1.2 解压并配置NodeJS1.3 验证是否安装成功2、使用yarn下载前端依赖2.1 安装yarn2.2 使用yarn下载前端依赖参考目标:在Windows下安装新版NodeJS,并使用yarn下载前端依赖,实现运行前端项目。 1、安装NodeJS 1.1 下载NodeJS安装包…

带你10分钟学会红黑树

前言&#xff1a; 我们都知道二叉搜索树&#xff0c;是一种不错的用于搜索的数据结构&#xff0c;如果二叉搜索树越接近完全二叉树&#xff0c;那么它的效率就会也高&#xff0c;但是它也存在的致命的缺陷&#xff0c;在最坏的情况下&#xff0c;二叉搜索树会退化成为单链表&am…

字典与数组第七讲:工作表数据计算时为什么要采用数组公式(一)

《VBA数组与字典方案》教程&#xff08;10144533&#xff09;是我推出的第三套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;字典是VBA的精华&#xff0c;我要求学员必学。7.1.3.9教程和手册掌握后&#xff0c;可以解决大多数工作中遇到的实际问题。…

谷歌地球引擎GEE账户注册的快速、百分百成功方法

本文介绍免费注册谷歌地球引擎&#xff08;Google Earth Engine&#xff0c;GEE&#xff09;账户的方便、快捷的最新方法&#xff1b;基于这一方法&#xff0c;只要我们创建一个谷歌Cloud Project&#xff0c;就可以直接访问GEE。 GEE在原本&#xff08;大概前几年的时候&#…

Redis-缓存穿透,缓存击穿,缓存雪崩

缓存穿透&#xff0c;缓存击穿&#xff0c;缓存雪崩 缓存穿透处理方案解决方案1 缓存空数据解决方案2 布隆过滤器 缓存击穿处理方案解决方案 1 互斥锁解决方案2 逻辑过期 缓存雪崩处理方案解决方案 1 给不同的key的过期时间设置添加一个随机值&#xff0c;降低同一个时段大量ke…

处理机调度的概念,层次联系以及七状态模型

1.基本概念 当有一堆任务要处理&#xff0c;但由于资源有限&#xff0c;这些事情没法同时处理。 这就需要确定某种规则来决定处理这些任务的顺序&#xff0c;这就是“调度”研究的问题。 2. 三个层次 1.高级调度&#xff08;作业调度&#xff09; 高级调度&#xff08;作业…

【10】c++设计模式——>依赖倒转原则

关于依赖倒转原则&#xff0c;对应的是两条非常抽象的描述&#xff1a; 1.高层模块不应该依赖低层模块&#xff0c;两个都应该依赖抽象。 2.抽象不应该依赖细节&#xff0c;细节应该依赖抽象。 先用人话解释一下这两句话中的一些抽象概念&#xff1a; 1.高层模块&#xff1a;可…

ROS(5)PX4仿真安装及运行

1、配置&#xff0c;提升下载速度 启动 $ cd clash-for-linux$ sudo bash start.sh$ source /etc/profile.d/clash.sh$ proxy_on 关闭 $ cd clash-for-linux$ sudo bash shutdown.sh$ proxy_off 2、安装PX4开源无人机 git clone https://github.com/PX4/PX4-Autopilot.git…

【软考】系统集成项目管理工程师(六)项目整体管理【6分】

一、 前言 1、项目管理三从四得 2、ITO共性总结 1、上一个过程的输出大部分是下-个过程的输入 2、计划和文件是不一样的 (每个输入都有计划和文件) 3、被批准的变更请求约等于计划 4、在执行和监控过程产生新的变更请求(变更请求包括变什么和怎么变&#xff0c;这是变更请求和…