【Spring Boot 源码学习】BootstrapRegistryInitializer 详解
Spring Boot 源码学习系列

BootstrapRegistryInitializer 详解
- 引言
- 往期内容
- 主要内容
- 1. 初识 BootstrapRegistryInitializer
- 2. 加载 BootstrapRegistryInitializer
- 3. BootstrapRegistryInitializer 的初始化
- 总结
引言
书接前文《初识 SpringApplication》,我们从 Spring Boot 的启动类 SpringApplication 上入手,了解了 SpringApplication 实例化过程。其中,有如下三块内容还未详细分析:

本篇博文就主要围绕 2.3 的内容展开,详细分析一下加载并初始化 BootstrapRegistryInitializer 及其相关的类的逻辑。

往期内容
在开始本篇的内容介绍之前,我们先来看看往期的系列文章【有需要的朋友,欢迎关注系列专栏】:
| Spring Boot 源码学习 |
| Spring Boot 项目介绍 |
| Spring Boot 核心运行原理介绍 |
| 【Spring Boot 源码学习】@EnableAutoConfiguration 注解 |
| 【Spring Boot 源码学习】@SpringBootApplication 注解 |
| 【Spring Boot 源码学习】走近 AutoConfigurationImportSelector |
| 【Spring Boot 源码学习】自动装配流程源码解析(上) |
| 【Spring Boot 源码学习】自动装配流程源码解析(下) |
| 【Spring Boot 源码学习】深入 FilteringSpringBootCondition |
| 【Spring Boot 源码学习】OnClassCondition 详解 |
| 【Spring Boot 源码学习】OnBeanCondition 详解 |
| 【Spring Boot 源码学习】OnWebApplicationCondition 详解 |
| 【Spring Boot 源码学习】@Conditional 条件注解 |
| 【Spring Boot 源码学习】HttpEncodingAutoConfiguration 详解 |
| 【Spring Boot 源码学习】RedisAutoConfiguration 详解 |
| 【Spring Boot 源码学习】JedisConnectionConfiguration 详解 |
| 【Spring Boot 源码学习】初识 SpringApplication |
| 【Spring Boot 源码学习】Banner 信息打印流程 |
| 【Spring Boot 源码学习】自定义 Banner 信息打印 |
主要内容
注意: 以下涉及 Spring Boot 源码 均来自版本 2.7.9,其他版本有所出入,可自行查看源码。
1. 初识 BootstrapRegistryInitializer
废话不多说,我们直接来看 BootstrapRegistryInitializer 接口的源码:
@FunctionalInterface
public interface BootstrapRegistryInitializer {void initialize(BootstrapRegistry registry);
}
阅读上述代码,可以看到 BootstrapRegistryInitializer 接口被 @FunctionalInterface 注解修饰。
@FunctionalInterface是 Java 8 中引入的一个注解,用于标识一个函数式接口。函数式接口是只有一个抽象方法的接口,常用于实现 Lambda 表达式和方法引用。
使用@FunctionalInterface注解可以向编译器指示该接口是一个函数式接口,从而在编译时进行类型检查,确保该接口 只包含一个抽象方法。此外,该注解还可以为函数式接口生成特殊的方法,如默认方法(default method)和 静态方法(static method),这些方法可以在接口中提供更多的功能,这里就不赘述了,感兴趣的朋友可以自行查阅相关函数式接口的资料。
BootstrapRegistryInitializer 接口只定义了一个 initialize 方法,该方法只有一个参数是 BootstrapRegistry;
BootstrapRegistry 是一个简单的对象注册表,它在启动和环境后处理期间都可用,直到ApplicationContext 准备好为止。它可用于注册可能创建成本较高或在 ApplicationContext 可用之前需要共享的实例。它的一个默认实现是 DefaultBootstrapContext ,后面我们会看到。
注册表使用 Class 作为键,这意味着每个给定类型只能存储一个实例。
addCloseListener(ApplicationListener) 方法可用于添加监听器,当 BootstrapContext 已关闭并且 ApplicationContext 完全准备好时,该监听器可以执行操作。例如,一个实例可能选择将自己注册为常规的 Spring bean,以便应用程序可以使用它。
简而言之,
BootstrapRegistry是一个用于存储和共享对象的注册表,这些对象在ApplicationContext准备好之前就可能已经被创建并需要被共享。
在 Spring Cloud Config 中,客户端通过向配置中心(Config Server)发送请求来获取应用程序的配置信息。而 BootstrapRegistryInitializer 就是负责将配置中心的相关信息注册到 Spring 容器中的。
2. 加载 BootstrapRegistryInitializer
this.bootstrapRegistryInitializers = new ArrayList<>(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
上述代码是 SpringApplication 的核心构造方法中的逻辑,它用于加载实现了 BootstrapRegistryInitializer 接口的类。
我们进入 getSpringFactoriesInstances 方法,查看如下:

我们看到了如下的代码 :
SpringFactoriesLoader.loadFactoryNames(type, classLoader);
这里是通过 SpringFactoriesLoader 类的 loadFactoryNames 方法来获取 META-INF/spring.factories 中配置 key 为 org.springframework.boot.BootstrapRegistryInitializer 的数据;
当然这些配置不在 Spring Boot 的 META-INF/spring.factories 中,我们上面提到 Spring Cloud Config 就是用 BootstrapRegistryInitializer 将配置中心的相关信息注册到 Spring 容器中,那我们就来看看 Spring Cloud Config 相关的配置。
如下是 Spring Cloud Config 的 Starter 依赖:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId><version>4.0.4</version>
</dependency>
导入上述依赖之后,相关的 META-INF/spring.factories 配置,我们发现是在如下的 jar 包里面【spring-cloud-config-client-4.0.4.jar】:

查看 META-INF/spring.factories 配置文件,我们可以看到如下:

# Spring Boot BootstrapRegistryInitializers
org.springframework.boot.BootstrapRegistryInitializer=\
org.springframework.cloud.config.client.ConfigClientRetryBootstrapper
有关 Spring Cloud Config 的内容,这里就不展开介绍了,感兴趣的小伙伴自行查阅 Spring Cloud Config 的官方文档。
3. BootstrapRegistryInitializer 的初始化
这里我们需要查看 SpringApplication 的 run(String... args) 方法,如下所示:

在上述的 createBootstrapContext 方法中,就对 BootstrapRegistryInitializer 进行初始化,我们继续往下看:

从上图中,我们可以看到这样一行代码:
this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
这里涉及如下的知识点:
this.bootstrapRegistryInitializers.forEach(): Java 8 的 Stream API,它用于遍历列表中的每个元素,并执行给定的操作【即initializer.initialize(bootstrapContext)】。(initializer) -> initializer.initialize(bootstrapContext): Lambda 表达式,这是 Java 8 引入的一个新特性,允许以更简洁的方式表示匿名方法。它表示一个接受BootstrapRegistryInitializer类型参数initializer,并调用其initialize(bootstrapContext)方法的功能。
简而言之,对于 this.bootstrapRegistryInitializers 列表中的每个 BootstrapRegistryInitializer,使用当前的 bootstrapContext 初始化它。这里的 bootstrapContext 其实就是 BootstrapRegistry 注册表的一个默认实现 DefaultBootstrapContext 。
从上述的 SpringApplication 的 run(String... args) 方法源码中,我们也可以看出 BootstrapRegistryInitializer 的初始化是在 Spring Boot 应用启动一开始进行的。
我们通过实现 BootstrapRegistryInitializer 接口并定义 initialize 方法,可以将自定义的 Bean 初始化器注册到 ApplicationContext 中。这样,在 Spring Boot 应用启动时,这些初始化器会被自动加载并执行,从而完成一些必要的初始化配置。
总结
本篇 Huazie 带大家详细分析了加载并初始化 BootstrapRegistryInitializer 的逻辑,这对于后续的 SpringApplication 运行流程的理解至关重要。
相关文章:
【Spring Boot 源码学习】BootstrapRegistryInitializer 详解
Spring Boot 源码学习系列 BootstrapRegistryInitializer 详解 引言往期内容主要内容1. 初识 BootstrapRegistryInitializer2. 加载 BootstrapRegistryInitializer3. BootstrapRegistryInitializer 的初始化 总结 引言 书接前文《初识 SpringApplication》,我们从 …...
预览功能实现
需求:将后端返回来的文字或者图片和视频展示在页面上。 <!-- 预览 --><el-dialog title"预览" :visible.sync"dialogPreviewVisible" width"50%" append-to-body :close-on-click-modal"false" close"Previe…...
canvas基础:绘制贝塞尔曲线
canvas实例应用100 专栏提供canvas的基础知识,高级动画,相关应用扩展等信息。 canvas作为html的一部分,是图像图标地图可视化的一个重要的基础,学好了canvas,在其他的一些应用上将会起到非常重要的帮助。 文章目录 bez…...
高项备考葵花宝典-项目范围管理输入、输出、工具和技术
项目范围管理包括确保项目“做”且“只做”所需的全部工作(即不能少做,也不能多做,如果多做,就要消耗团队额外的时间和资源,并且无法被认可),以成功完成项目。项目范围管理主要在于定义和控制哪…...
在表格中显示字典的内容(根据后端返回的数据)vue3
进入页面,调接口,后端返回数据,indexType为0或者1,要用这个数据显示字典的内容 用插槽拿到数据 写一个函数,在模板中使用 const { proxy } getCurrentInstance(); // 字典-指标类型 const { index_type } proxy.u…...
编程怎么学才能快速入门,分享一款中文编程工具快速学习编程思路,中文编程工具之边条主控菜单构件简介
编程怎么学才能快速入门,分享一款中文编程工具快速学习编程思路,中文编程工具之边条主控菜单构件简介 一、前言 零基础自学编程,中文编程工具下载,中文编程工具构件之扩展系统菜单构件教程编程系统化教程链接https://jywxz.blog…...
MySQL索引下推
文章目录 索引下推为什么范围查找Mysql没有用索引下推优化? 说到索引下推,应该会有不少人对它很陌生的,那么什么是索引下推,今天我们就来谈谈它到底是什么样? 索引下推 索引下推:MySQL 5.6 引入的索引下推…...
代码随想录刷题题Day3
刷题的第三天,希望自己能够不断坚持下去,迎来蜕变。😀😀😀 刷题语言:C / Python Day3 任务 ● 链表理论基础 ● 203.移除链表元素 ● 707.设计链表 ● 206.反转链表 1 链表理论基础 链表:通过…...
GO学习之 单例模式 sync.Once
GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 10、GO学习之 网络通信(Net/Htt…...
应用安全四十三:无密码认证安全
什么是无密码认证? 无密码认证是一种新兴的安全技术和身份认证手段,是用密码以外的东西验证软件用户身份的过程,旨在替代传统的用户账号和密码认证方法,提高账号的安全性和用户体验。无密码技术通过生物识别、多因素认证、基于硬…...
Lattice-Based Blind Signatures: Short, Efficient, and Round-Optimal
目录 摘要引言 Lattice-Based Blind Signatures: Short, Efficient, and Round-Optimal CCS 2023 摘要 我们提出了一种基于随机预言机启发式和标准格问题(环/模块SIS/LWE和NTRU)的2轮盲签名协议,签名大小为22KB。该协议是全面优化的…...
Qt/C++音视频开发57-切换音视频轨道/切换节目流/分别切换音频视频轨道
一、前言 对各种音视频文件格式的支持,是一个播放器的基础功能。一般的音视频文件只有1路流,比如音频文件只有1路音频流,视频文件只有1路音频1路视频流,实践过程中发现,还有一种ts格式的文件,可能有多路流…...
深度学习之基于Django文本情感分析识别系统
欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 深度学习在文本情感分析领域的应用已经取得了显著的进展。Django是一个流行的Python Web框架,它可以帮助…...
138. 随机链表的复制 --力扣 --JAVA
题目 给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点…...
Python Flask 框架开发
1. Python 代码示例(使用 Flask 框架) 1.1 安装依赖库 pip install flask flask_sqlalchemy flask_login flask_wtf 1.2 主应用文件 app.py from flask import Flask, request, jsonify, redirect, url_for, render_template, flash from flask_sqla…...
k8s安装-学习环境
目录 环境准备 配置hosts 关闭防火墙 关闭交换分区 调整swappiness参数 关闭setlinux Ipv4转发 时钟同步 安装Docker 配置Yum源 安装 配置 启动 日志 安装k8s 配置Yum源 Master节点 安装 初始化 配置kubectl 部署CNI网络插件 Node节点 检查 环境准备 准…...
Vue3动态表单
示例代码如下: // 引入需要的依赖包 import { ref, reactive } from vue; import { useForm } from /composables/useForm;// 定义表单数据模型 const formModel reactive({name: ,age: ,gender: , });// 使用自定义的useForm函数创建表单实例 const { register, …...
2312skia,15vulkan及技巧
ANGLE介绍 ANGLE,把OpenGLES2或3调用转换为DirectX9,11或OpenGL调用.这些说明记录了如何在Windows或Linux上使用ANGLE而不是本地OpenGL后端. 细节 gclient sync下载ANGLE的源码及Skia的其他仅测试依赖项. 要针对ANGLE构建Skia测试工具,请添加skia_use_angletrue到args.gn文件…...
TLSF算法概念,原理,内存碎片问题分析
TLSF算法介绍 TLSF(Two-Level Segregated Fit,两级分割适应算法)。 第一级(first level,简称fl):将内存大小按2的幂次方划分一个粗粒度的范围,如一个72字节的空闲内存的fl是6(72介…...
sharding-jdbc实现分库分表
shigen日更文章的博客写手,擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长,分享认知,留住感动。 😅😅最近几天的状态有点不对,所以有几天没有更新了。 当我们的数据量比较大…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...
【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
