【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 注解修饰。

@FunctionalInterfaceJava 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 为 BootstrapRegistryInitializer 的数据;

当然这些配置不在 Spring BootMETA-INF/spring.factories 中,我们上面提到 Spring Cloud Config 就是用 BootstrapRegistryInitializer 将配置中心的相关信息注册到 Spring 容器中,那我们就来看看 Spring Cloud Config 相关的配置。

如下是 Spring Cloud ConfigStarter 依赖:

<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 的初始化

这里我们需要查看 SpringApplicationrun(String... args) 方法,如下所示:

在这里插入图片描述

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

在这里插入图片描述

从上图中,我们可以看到这样一行代码:

this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));

这里涉及如下的知识点:

  • this.bootstrapRegistryInitializers.forEach() : Java 8Stream API,它用于遍历列表中的每个元素,并执行给定的操作【即 initializer.initialize(bootstrapContext) 】。
  • (initializer) -> initializer.initialize(bootstrapContext)Lambda 表达式,这是 Java 8 引入的一个新特性,允许以更简洁的方式表示匿名方法。它表示一个接受BootstrapRegistryInitializer 类型参数 initializer,并调用其 initialize(bootstrapContext) 方法的功能。

简而言之,对于 this.bootstrapRegistryInitializers 列表中的每个 BootstrapRegistryInitializer,使用当前的 bootstrapContext 初始化它。这里的 bootstrapContext 其实就是 BootstrapRegistry 注册表的一个默认实现 DefaultBootstrapContext

从上述的 SpringApplicationrun(String... args) 方法源码中,我们也可以看出 BootstrapRegistryInitializer 的初始化是在 Spring Boot 应用启动一开始进行的。

我们通过实现 BootstrapRegistryInitializer 接口并定义 initialize 方法,可以将自定义的 Bean 初始化器注册到 ApplicationContext 中。这样,在 Spring Boot 应用启动时,这些初始化器会被自动加载并执行,从而完成一些必要的初始化配置。

总结

本篇 Huazie 带大家详细分析了加载并初始化 BootstrapRegistryInitializer 的逻辑,这对于后续的 SpringApplication 运行流程的理解至关重要。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

A*算法学习

系列文章目录 前言 在总结 2023华为软件精英挑战赛——全赛段思路分享与总结 - 知乎 (zhihu.com)时&#xff0c;发现自己还有很多技术细节没搞懂&#xff0c;这里看静态全局路径规划最常见的A*算法&#xff0c;这个博主讲得很好&#xff1a; A-Star&#xff08;A*&#xff0…

第十五届蓝桥杯(Web 应用开发)模拟赛 2 期-大学组(详细分析解答)

目录 1.相不相等 1.1 题目要求 1.2 题目分析 1.3 源代码 2.三行情书 2.1 题目要求 2.2 题目分析 2.3 源代码 3.电影院在线订票 3.1 题目要求 3.2 题目分析 3.3 源代码 4.老虎坤&#xff08;不然违规发不出来&#xff09; 4.1 题目要求 4.2 题目分析 4.3 源代码 …

mac 聚焦搜索不显示

我是连搜索框都不显示&#xff0c;不是搜索结果显示异常 点右上角的搜索按钮都毫无反应 我检查过快捷键之类的设置&#xff0c;都正常&#xff0c;最后是通过删除文件解决的 cd ~/Library/Preferences/ rm com.apple.Spotlight.plist 重启 mac 参考 Spotlight Search Not W…

“rhdf5filters.so’ not found when install ‘glmGamPoi‘ package

在R中安装glmGamPoi包的时候&#xff0c;出现了如下报错&#xff1a; install.packages(glmGamPoi) 尝试方案一&#xff1a; sudo apt install pkg-config libhdf5-dev安装lighdf5-dev&#xff0c;并将安装路径链接至usr/lib/文件。 locate rhdf5filters.so sudo ln -s /hom…

java-var类型推断的使用时机

写在前面&#xff1a; 在jdk9的时候引入了var关键字&#xff0c;但是这是一把双刃剑&#xff0c;使用的好的话可以简化代码提高可读性&#xff0c;如果使用的不好的话会导致反效果。 文章目录 使用原则推荐使用时机new关键字创建对象类型不重要for循环 不适合与泛型大量结合字…

【Java学习笔记】75 - 算法优化入门 - 马踏棋盘问题

一、意义 1.算法是程序的灵魂&#xff0c;为什么有些程序可以在海量数据计算时&#xff0c;依然保持高速计算? 2.拿老韩实际工作经历来说&#xff0c;在Unix下开发服务器程序&#xff0c;功能是要支持上千万人同时在线&#xff0c;在上线前&#xff0c; 做内测&#xff0c;一…

vuepress-----9、PWA

# 9、PWA 使用babel 的插件形式 [vuepress/pwa,{serviceWorker: true,updatePopup: {message: "New content is available.",buttonText: "Refresh"}}]提供 Manifest 和 icons (opens new window) 拷贝到public目录下 发布后出现 service workers [外链图片…

Spring第三课,Lombok工具包下载,对应图书管理系统列表和登录界面的后端代码,分层思想

目录 一、Lombok工具包下载 二、前后端互联的图书管理系统 规范 三、分层思想 三层架构&#xff1a; 1.表现层 2.业务逻辑层 3.数据层 一、Lombok工具包下载 这个工具包是为了做什么呢&#xff1f; 他是为了不去反复的设置setting and getting 而去产生的工具包 ⚠️工具…

二叉树(判断是否为对称二叉树)

题目&#xff08;力扣&#xff09;&#xff1a; 观察题目&#xff0c;只需判断该二叉树是否对称。 判断二叉树是否对称&#xff0c;就可以换位去判断该二叉树的左子树和右子树是否对称。 这时就可以写一个辅助函数来方便判断。 该函数是判断两颗树是否镜像对称&#xff0c;这…

【华为数通HCIP | 网络工程师】821刷题日记-IS-IS(2)

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

Docker—更新应用程序

在本部分中&#xff0c;你将更新应用程序和映像。您还将了解如何停止和移除容器。 一、更新源代码 在以下步骤中&#xff0c;当您没有任何待办事项列表项时&#xff0c;您将把“空文本”更改为“您还没有待办事项&#xff01;在上面添加一个&#xff01;” 1、在src/static/…

电子学会C/C++编程等级考试2022年12月(三级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:鸡兔同笼 一个笼子里面关了鸡和兔子(鸡有2只脚,兔子有4只脚,没有例外)。已经知道了笼子里面脚的总数a,问笼子里面至少有多少只动物,至多有多少只动物。 时间限制:1000 内存限制:65536输入 一行,一个正整数a (a < 327…

分发测试应用平台怎么用之应用详情功能

我的应用 应用功能引导 ●您会看到以下页面&#xff0c;下图为功能的解释方便您的运行 我的应用-详情-应用详情 ●我们点击应用详情数字③&#xff0c;点击应用详情&#xff0c;下图是对详情页的功能介绍。 详情-应用设置 ●详情-应用设置-下图为应用设置的上半部分 ●下图为应…

保障海外业务发展,Coremail提供高效安全的海外通邮服务

11月22日&#xff0c;Coremail举办《全球通邮&#xff1a;如何保障安全、快捷的海外中继服务》直播分享会&#xff0c;直播会上Coremail安全团队和直播嘉宾复旦大学校园信息化办公室徐艺扬老师就海外中继服务进行了深度分享。 ​ 海外通邮困难重重 境外垃圾邮件数量居高不下…

力扣日记11.28-【二叉树篇】二叉树的最小深度

力扣日记&#xff1a;【二叉树篇】二叉树的最小深度 日期&#xff1a;2023.11.28 参考&#xff1a;代码随想录、力扣 111. 二叉树的最小深度 题目描述 难度&#xff1a;简单 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点…

快速入门opencv(python版)

Open Source Computer Vision Library。OpenCV是一个&#xff08;开源&#xff09;发行的跨平台计算机视觉库&#xff0c;可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C 类构成&#xff0c;同时提供了Python、Ruby、MATLAB等语言的…

后端项目连接数据库-添加MyBatis依赖并检测是否成功

一.在pom.xml添加Mybatis相关依赖 在Spring Boot项目中&#xff0c;编译时会自动加载项目依赖&#xff0c;然后使用依赖包。 需要在根目录下pom.xml文件中添加Mybatis依赖项 <!-- Mybatis整合Spring Boot的依赖项 --> <dependency><groupId>org.mybatis.s…

数据结构---树

树概念及结构 1.树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因 为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的 有一个特殊的结点&#xff0c…

血的教训---入侵redis并免密登录redis所在服务器

血的教训—入侵redis并免密登录redis所在服务器 今天就跟着我一起来入侵redis并免密登录redis所在服务器吧&#xff0c;废话不多说&#xff0c;我们直接开始吧。 这是一个体系的学习步骤&#xff0c;当然如果基础扎实的话可以继续往下面看 以下都是关联的文章&#xff0c;可以学…

4.6-容器的端口映射

首先&#xff0c;我们来拉取Nginx的image镜像。 docker pull nginx 接下来我们创建一个Nginx的容器。 docker run --name nginx -d nginx 但是&#xff0c;这样启动nginx容器的话我们没法访问。这个时候怎么办呢&#xff1f;就需要将Nginx这个服务暴露给外面的世界。 这时可以使…