【Spring Boot 源码学习】BootstrapRegistry 初始化器实现

《Spring Boot 源码学习系列》

在这里插入图片描述

BootstrapRegistry 初始化器实现

  • 一、引言
  • 二、往期内容
  • 三、主要内容
    • 3.1 BootstrapRegistry
    • 3.2 BootstrapRegistryInitializer
    • 3.3 BootstrapRegistry 初始化器实现
      • 3.3.1 定义 DemoBootstrapper
      • 3.3.2 添加 DemoBootstrapper
  • 四、总结

一、引言

前面的博文《BootstrapRegistryInitializer 详解》,Huazie 带大家一起详细分析了 Spring Boot 启动时加载并初始化 BootstrapRegistryInitializer 及其相关的类的逻辑。本篇就让我们自定义 BootstrapRegistryInitializer 接口实现,以此来执行自定义的初始化操作【如注册自定义的 Bean、添加 BootstrapContext 关闭监听器】。

在这里插入图片描述

二、往期内容

在开始本篇的内容介绍之前,我们先来看看往期的系列文章【有需要的朋友,欢迎关注系列专栏】:

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 源码学习】BootstrapRegistryInitializer 详解
【Spring Boot 源码学习】ApplicationContextInitializer 详解
【Spring Boot 源码学习】ApplicationListener 详解
【Spring Boot 源码学习】SpringApplication 的定制化介绍
【Spring Boot 源码学习】BootstrapRegistry 详解
【Spring Boot 源码学习】深入 BootstrapContext 及其默认实现

三、主要内容

注意: 以下涉及 Spring Boot 源码 均来自版本 2.7.9,其他版本有所出入,可自行查看源码。

3.1 BootstrapRegistry

在《BootstrapRegistry 详解》 中,Huazie 详细介绍了 BootstrapRegistry 的源码,这有助于下面介绍的 BootstrapRegistry 初始化器的实现逻辑,有不知道的朋友们直接查看即可,这里不再赘述。

3.2 BootstrapRegistryInitializer

在《BootstrapRegistryInitializer 详解》 中,Huazie 详解分析了加载并初始化 BootstrapRegistryInitializer 的逻辑,这同样有助于
理解下面将要讲解的内容,还不熟悉的朋友们赶紧花点时间了解下,这里不再赘述。

3.3 BootstrapRegistry 初始化器实现

3.3.1 定义 DemoBootstrapper

下面我们来定义一个类 DemoBootstrapper,该类实现 BootstrapRegistryInitializer 接口,如下:

public class DemoBootstrapper implements BootstrapRegistryInitializer {
    @Override
    public void initialize(BootstrapRegistry registry) {
        // 注册一些自定义的对象 或者 加载自定义的一些配置
    }
}

在《BootstrapRegistryInitializer 详解》 的 3.2 小节,Huazie 介绍了 BootstrapRegistryInitializer 的加载过程,上述我们自定义的 DemoBootstrapper 也会在 Spring Boot 启动引导阶段进行加载并初始化。

上述定义中,我们只是展示了一个空实现的类,其中的 initialize 方法还未做处理。

至于 initialize 方法中该添加哪些逻辑,这就要看它的参数 BootstrapRegistry 接口了。

下面代码,Huazie 演示了如何 注册自定义的对象,以及添加 引导上下文关闭事件监听器

// 注册 User对象,它就是一个简单的 POJO 类,含两个成员变量:名称 name 和年龄 age
registry.register(User.class, context -> new User("Huazie", 18));
// 添加 BootstrapContext关闭 监听器
registry.addCloseListener(new DemoBootstrapContextClosedListener());

DemoBootstrapContextClosedListener ,即引导上下文关闭事件监听器,相关演示代码如下:

public class DemoBootstrapContextClosedListener implements ApplicationListener<BootstrapContextClosedEvent>, Ordered {
    @Override
    public void onApplicationEvent(BootstrapContextClosedEvent event) {
        BootstrapContext bootstrapContext = event.getBootstrapContext();
        if (bootstrapContext.isRegistered(User.class)) {
            System.out.println("BootstrapContext关闭时获取User:" + bootstrapContext.get(User.class));
        }
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

虽然上面添加了引导上下文关闭事件监听器,但是我们还不知道什么时候它会被执行。

DemoBootstrapContextClosedListener 中,我们看到了 BootstrapContext 的使用,显然这里涉及到了引导上下文的实际使用场景,由于篇幅受限,将在下篇介绍,大家不妨期待一下。

另外,在 DemoBootstrapContextClosedListener 中,还看到它实现了 Ordered 接口【spring-core 包中的接口】。

那么在事件监听器中,这个 Ordered 接口是用来做什么的呢?

在回答这个问题之前,我们先来看看 Ordered 接口的源码:

public interface Ordered {
	int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
	int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
	int getOrder();
}

Ordered 接口定义了两个常量和一个方法:

  • HIGHEST_PRECEDENCE:最高优先级值的有用常数【最小的 Integer 值】
  • LOWEST_PRECEDENCE :最低优先级值的有用常数【最大的 Integer 值】
  • int getOrder() :获取当前对象的优先级值【值越小,优先级越高】

源码中对于 Ordered 接口是这样说的:

它可以被需要排序的对象实现,例如在集合中。实际的排序可以被解读为优先级排序,其中第一个对象(即有着最低的排序值)具有最高的优先级。

当然,Ordered 接口还有一个扩展接口,即优先级标记接口 PriorityOrderedPriorityOrdered 对象总是优先于普通 Ordered 对象,无论它们的排序值如何。当对一组 Ordered 对象进行排序时,PriorityOrdered 对象和普通 Ordered 对象实际上被视为两个独立的子集,PriorityOrdered 对象子集先于普通 Ordered 对象子集,并在这些子集内部应用相对排序。

上述排序逻辑请查看 spring-core 包中的 AnnotationAwareOrderComparator 类 和 OrderComparator 类,这里不再赘述了。

现在可以回答上面的问题了:在事件监听器中实现 Ordered 接口,可以用来确保 多个监听同一事件的监听器 可以按照我们 预定的顺序执行

3.3.2 添加 DemoBootstrapper

不过,要想能够加载到自定义的 DemoBootstrapper ,我们还需要将它添加到 bootstrapRegistryInitializers 中才可以。

// SpringApplication的私有变量
private List<BootstrapRegistryInitializer> bootstrapRegistryInitializers;

那么,我们该如何添加呢?

通过阅读 SpringApplication 的源码,可以总结如下的两种方式:

  • META-INF/spring.factories 中添加 org.springframework.boot.BootstrapRegistryInitializer 的配置。这种方式,我们从 《BootstrapRegistryInitializer 详解》 的 3.2 小节可见一斑。

    org.springframework.boot.BootstrapRegistryInitializer=com.example.demo.DemoBootstrapper
    
  • 通过 SpringApplication 中的 addBootstrapRegistryInitializer 方法添加。其实这里在笔者的《SpringApplication 的定制化介绍》中的 1.5 小节也提及过。

    SpringApplication springApplication = new SpringApplication(DemoApplication.class);
    springApplication.addBootstrapRegistryInitializer(new DemoBootstrapper());
    // 其他省略。。。
    

四、总结

本篇 Huazie 介绍了如何自定义 BootstrapRegistry 初始化器实现,其中演示如何在引导上下文中注册了自定义的对象以及如何在引导上下文中添加引导上下文关闭事件监听器

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

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

相关文章

[机缘参悟-160] :人的感知系统是及其有限的,从电磁波的频谱、声波的声谱,看人类只看感知到物质世界的一小部分,无法感知到全部真相

目录 一、人自身是如何感知物质世界的&#xff1f; 1.1 五官 1.2 关于视觉、光、电磁波 1.2.1 视觉系统 1.2.2 感光细胞 ​编辑 1.2.3 光波与人眼的光波范围 1.2.4 电磁波 1.2.5 通过科学仪器和技术可以拓展人对电磁波的感知 1.2.6 太阳光的光谱 1.2.6 光不仅仅用于…

安卓虚拟机ART和Dalvik

目录 一、JVM和Dalvik1.1 基于栈的虚拟机字节码指令执行过程 1.2 基于寄存器的虚拟机 二、ART与Dalvikdex2aotAndroid N的运作方式 三、总结 一、JVM和Dalvik Android应用程序运行在Dalvik/ART虚拟机&#xff0c;并且每一个应用程序对应有一个单独的Dalvik虚拟机实例。 Dalvik…

GO泛型相关

通过引入 类型形参 和 类型实参 这两个概念&#xff0c;我们让一个函数获得了处理多种不同类型数据的能力&#xff0c;这种编程方式被称为 泛型编程。 2. Go的泛型 类型形参 (Type parameter)类型实参(Type argument)类型形参列表( Type parameter list)类型约束(Type constr…

50 vmalloc 的实现

前言 这里说的是 内核中分配按页分配的场景 常用于 驱动什么的, 分配 中大型空间 由于 连续的 n 个页是分别使用 alloc_pages 分配的, 因此是 虚拟地址空间连续, 但是 物理地址空间不连续 如何分配对象 两个步骤, __get_vm_area_node 获取为 size 分配的 vma 区间, 然后…

Spark(1)-wordCount入门

1. 创建Maven项目 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/P…

java 基础(核心知识搭配代码)

前言 java的学习分为了上部分以及下部分进行学习&#xff0c;上部分就是对于java的基础知识&#xff0c;面向对象上&#xff0c;面向对象下&#xff0c;异常操作&#xff0c;javaApi&#xff1b;下部主要是集合&#xff0c;泛型&#xff0c;反射&#xff0c;IO流&#xff0c;J…

用冒泡排序模拟C语言中的内置快排函数qsort!

目录 ​编辑 1.回调函数的介绍 2. 回调函数实现转移表 3. 冒泡排序的实现 4. qsort的介绍和使用 5. qsort的模拟实现 6. 完结散花 悟已往之不谏&#xff0c;知来者犹可追 创作不易&#xff0c;宝子们&#xff01;如果这篇文章对你们有帮助的话&#xff0c;别忘了给个免…

逻辑回归与决策边界解析

目录 前言1 逻辑回归基础1.1 Sigmoid函数&#xff1a;打开分类之门1.2 决策函数&#xff1a;划定分类界限1.3 逻辑回归详解 2 决策边界2.1 线性决策边界2.2 非线性决策边界2.3 决策边界的优化 3 应用与实例3.1 垃圾邮件分类&#xff1a;精准过滤3.2 金融欺诈检测&#xff1a;保…

关于调试出现的问题(console.log)

偶然之间发现了一个关于控制台打印的问题&#xff0c;感觉大家偶尔可能会遇到这种问题&#xff0c;这种问题的出现并不是代码的错误哦 首先我们先看代码&#xff1a; let arr [{ a: 1 },{ b: 1 } ] console.log(arr) arr[0].a console.log(arr) 可能大家预想的打印结果如下&…

C++——模版

前言&#xff1a;哈喽小伙伴们好久不见&#xff0c;这是2024年的第一篇博文&#xff0c;我们将继续C的学习&#xff0c;今天这篇文章&#xff0c;我们来习一下——模版。 目录 一.什么是模版 二.模版分类 1.函数模版 2.类模板 总结 一.什么是模版 说起模版&#xff0c;我们…

MATLAB图像噪声添加与滤波

在 MATLAB 中添加图像噪声和进行滤波通常使用以下函数&#xff1a; 添加噪声&#xff1a;可以使用imnoise函数向图像添加各种类型的噪声&#xff0c;如高斯噪声、椒盐噪声等。 滤波&#xff1a;可以使用各种滤波器对图像进行滤波处理&#xff0c;例如中值滤波、高斯滤波等。 …

Linux笔记-1

概述 简介 Linux是现在服务器上最常用的操作系统(OS - Operating system) - 所谓的操作系统本质上也是一个软件&#xff0c;是一个可以运行其他软件的容器如果一台服务器&#xff0c;没有安装操作系统&#xff0c;此时称之为裸机。裸机可以使用&#xff0c;在使用的时候需要使…

如何恢复edge的自动翻译功能

介绍&#xff1a;对于英文不好的小伙伴&#xff0c;把英语翻译成中文是有帮助的&#xff0c;而edge可以直接对英文页面翻译这一功能更是受人喜爱&#xff0c;但是&#xff0c;最近发现这一项功能消失了。 原始界面&#xff1a; 下面展示如何恢复该功能。 1.打开edge&#xff…

提升CKA认证成功率:Kubernetes Ingress七层代理全攻略!

往期精彩文章 : 提升CKA考试胜算&#xff1a;一文带你全面了解RBAC权限控制&#xff01;揭秘高效运维&#xff1a;如何用kubectl top命令实时监控K8s资源使用情况&#xff1f;CKA认证必备&#xff1a;掌握k8s网络策略的关键要点提高CKA认证成功率&#xff0c;CKA真题中的节点维…

AI大模型分析:数据背后隐藏的故事!

在当今的数字时代&#xff0c;人工智能&#xff08;AI&#xff09;大模型已经成为挖掘和解读庞大数据集背后故事的强大工具。这些模型通过分析复杂的数据模式&#xff0c;不仅揭示了数据的表面信息&#xff0c;还深入挖掘出潜藏的含义和联系&#xff0c;为我们提供了前所未有的…

初识C语言—常见关键字

变量的命名最好有意义 名字必须是字母&#xff0c;数字&#xff0c;下划线组成&#xff0c;不能有特殊字符&#xff0c;同时不能以数字开头 变量名不能是关键字 typedef---类型定义&#xff0c;类型重命名 #include <stdio.h>typedef unsigned int uint; //将unsigne…

VBA数据库解决方案第九讲:打开数据库记录集,所得数据回填

《VBA数据库解决方案》教程&#xff08;版权10090845&#xff09;是我推出的第二套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;是学完字典后的另一个专题讲解。数据库是数据处理的利器&#xff0c;教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法…

详解 Rope (Opal-03a) 的变化

文章目录 &#xff08;一&#xff09;特点&#xff08;二&#xff09;使用流程&#xff08;三&#xff09;界面&#xff08;四&#xff09;详解&#xff08;4.1&#xff09;目录区域⭐Start Rope⭐Video Folder⭐Output Folder⭐Faces Folder &#xff08;4.2&#xff09;预览控…

幻兽帕鲁专用服务器搭建之Linux部署配置教程

大家好我是飞飞&#xff0c;上一期我分享了Windows系统的幻兽帕鲁服务器搭建教程。因为幻兽帕鲁这游戏对服务器的配置有一定的要求&#xff0c;很多小伙伴就寻思用Linux系统搭建占用会不会小一点&#xff1f;有计算机基础的小伙伴都知道Linux系统和Windows系统相比&#xff0c;…

带你玩转java封装和继承(上)

上次带大家学习了java里面比较重要的知识点类和对象&#xff0c;而且我们知道java是一门面向对象的语言&#xff0c;有时一个程序里可能有很多类&#xff0c;那么这么多类他们之间有什么联系吗&#xff1f;今天就带大家学习一下java类之间的关系。 什么是继承&#xff1a; 我们…