【Spring Boot 源码学习】BootstrapRegistry 详解

这篇具有很好参考价值的文章主要介绍了【Spring Boot 源码学习】BootstrapRegistry 详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

《Spring Boot 源码学习系列》

bootstrapregistry,开发框架-Spring Boot,spring boot,源码学习,对象注册表,Scope

一、引言

前面的博文《BootstrapRegistryInitializer 详解》,Huazie 带大家一起详细分析了 Spring Boot 启动时加载并初始化 BootstrapRegistryInitializer 及其相关的类的逻辑。其中有个 BootstrapRegistry 接口只是简单提及,本篇就详细分析一下 BootstrapRegistry 接口,这对于我们后续理解 《BootstrapRegistry 初始化器实现》的内容至关重要。

bootstrapregistry,开发框架-Spring Boot,spring boot,源码学习,对象注册表,Scope

二、往期内容

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

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 源码 均来自版本 2.7.9,其他版本有所出入,可自行查看源码。

在 《BootstrapRegistryInitializer 详解》 的 3.1 小节,我们对 BootstrapRegistry 进行了初步的介绍:它是一个用于存储和共享对象的注册表,这些对象在 ApplicationContext 准备好之前就可能已经被创建并需要被共享。

3.1 源码初识

首先让我们来看看 BootstrapRegistry 的源码:

public interface BootstrapRegistry {

	<T> void register(Class<T> type, InstanceSupplier<T> instanceSupplier);

	<T> void registerIfAbsent(Class<T> type, InstanceSupplier<T> instanceSupplier);

	<T> boolean isRegistered(Class<T> type);

	<T> InstanceSupplier<T> getRegisteredInstanceSupplier(Class<T> type);

	void addCloseListener(ApplicationListener<BootstrapContextClosedEvent> listener);

	@FunctionalInterface
	interface InstanceSupplier<T> {

		T get(BootstrapContext context);

		default Scope getScope() {
			return Scope.SINGLETON;
		}

		default InstanceSupplier<T> withScope(Scope scope) {
			// 。。。
		}

		static <T> InstanceSupplier<T> of(T instance) {
			return (registry) -> instance;
		}

		static <T> InstanceSupplier<T> from(Supplier<T> supplier) {
			return (registry) -> (supplier != null) ? supplier.get() : null;
		}

	}

	enum Scope {
		SINGLETON,
		PROTOTYPE
	}

}

它包含了 5 个方法,1个内部接口类,1个内部枚举类,下面我们一一来介绍下:

3.2 register 方法

register 方法,包含两个参数:

  • Class<T> type :实例类型
  • InstanceSupplier<T> instanceSupplier :实例供应者

该方法用于将特定类型注册到注册表中。如果指定的类型已经被注册,并且尚未作为单例获取,那么它将被替换。

3.3 registerIfAbsent 方法

registerIfAbsent 方法,包含两个参数:

  • Class<T> type :实例类型
  • InstanceSupplier<T> instanceSupplier :实例供应者

如果尚未存在特定类型的注册,则向注册表中注册该类型。

3.4 isRegistered 方法

isRegistered 方法,只有一个参数:

  • Class<T> type :实例类型

该方法用于返回给定类型是否已注册。如果给定类型已经注册,则返回 true,否则,返回 false

3.5 getRegisteredInstanceSupplier 方法

getRegisteredInstanceSupplier 方法,也只有一个参数:

  • Class<T> type :实例类型

该方法返回给定类型的任何现有的 BootstrapRegistry.InstanceSupplier

3.6 addCloseListener 方法

addCloseListener 方法,只有一个参数:

  • ApplicationListener<BootstrapContextClosedEvent> listener :待添加的监听器

该方法用于添加一个 ApplicationListener,当 BootstrapContext 关闭并且 ApplicationContext 已经准备就绪时,该监听器将与 BootstrapContextClosedEvent 一起被调用。

3.7 InstanceSupplier 内部接口类

InstanceSupplier 内部接口类是用于提供实际实例的供应者。

它定义了一个 1 个普通方法,2 个默认方法,2 个静态方法。

知识拓展:
Java 8 开始,支持在接口中定义默认方法和静态方法。

  • 默认方法(Default Method)允许你在接口中添加一个有默认实现的非抽象方法。这使得接口可以更加灵活地扩展,而不需要破坏与现有代码的兼容性。默认方法使用关键字 default 进行声明,并提供了具体的实现。
  • 静态方法(Static Method)允许你在接口中定义一个静态方法,该方法可以在不创建接口实例的情况下调用。静态方法使用关键字 static 进行声明,并可以直接通过接口名来调用。

3.7.1 get 方法

get 方法,只包含一个参数:

  • BootstrapContext context :BootstrapContext 是一个用于获取其他引导实例的上下文

该方法是工厂方法,用于在需要时创建实例,后续我们在讲解 DefaultBootstrapContext 时也会涉及。

3.7.2 getScope 默认方法

getScope 默认方法,用于返回提供的实例的作用域;如果该方法没有被重写,则默认返回 Scope.SINGLETON

3.7.3 withScope 默认方法

default InstanceSupplier<T> withScope(Scope scope) {
	Assert.notNull(scope, "Scope must not be null");
	InstanceSupplier<T> parent = this;
	return new InstanceSupplier<T>() {
		@Override
		public T get(BootstrapContext context) {
			return parent.get(context);
		}

		@Override
		public Scope getScope() {
			return scope;
		}
	};
}

通过阅读上述代码可知,该方法根据其参数 scope ,返回一个指定作用域的新的 BootstrapRegistry.InstanceSupplier 的匿名对象,该匿名对象重写了 getgetScope 方法。这里使用匿名对象的好处就是可以在不定义新类的情况下快速地创建一个具有特定行为的对象。

细心的读者们,可能发现了匿名对象的 get 方法中,使用了 withScope 方法中定义的变量 parent,它被用来存储当前对象的引用 this

那么这里的 parent ,能不能直接替换成 this 呢?

显然是不可以的,this 关键字用在匿名内部类中,指代的是该匿名内部类本身,而不是外部对象。而匿名对象这里的重写的 get 方法,实际上需要调用 withScope 方法所在的对象的 get 方法来实现功能。如果这里用 this,实际上就是自己调自己,一直无限递归调用,最终导致栈溢出错误。

3.7.4 of 静态方法

该静态方法是一个工厂方法,用于为给定实例创建一个BootstrapRegistry.InstanceSupplier

return (registry) -> instance;

这里采用了 Java 8Lambda 表达式,也相当于如下的写法:

return new InstanceSupplier<T>() {
    @Override
    public T get(BootstrapContext registry) {
        return instance;
    }
};

3.7.5 from 静态方法

该静态方法也是一个工厂方法,用于通过一个 Supplier 创建BootstrapRegistry.InstanceSupplier

return (registry) -> (supplier != null) ? supplier.get() : null;

这里也是用了 Java 8Lambda 表达式,相当于如下的写法:

return new InstanceSupplier<T>() {
    @Override
    public T get(BootstrapContext registry) {
        return (supplier != null) ? supplier.get() : null;
    }
};

知识点:SupplierJava 8 开始引入,作为 java.util.function 包的一部分,它与 Lambda 表达式一起被引入,以支持函数式编程范式。该接口是为了简化无参数方法的表示,特别是在需要延迟执行或创建对象时。Supplier 接口只有一个抽象方法 get(),它不接受任何参数,但返回一个通用类型的值。

3.8 Scope 内部枚举类

Scope 表示一个实例的作用域,它只包含两个枚举变量,分别是:

  • SINGLETON :单例实例。InstanceSupplier 只会被调用一次,并且每次调用都会返回相同的实例。
  • PROTOTYPE :原型实例。InstanceSupplier 将在需要实例时被调用。

四、总结

本篇 Huazie 带大家通读了 BootstrapRegistry 的相关源码,这些内容对于后面的源码学习至关重要。文章来源地址https://www.toymoban.com/news/detail-831158.html

到了这里,关于【Spring Boot 源码学习】BootstrapRegistry 详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Spring Boot 源码学习】RedisAutoConfiguration 详解

    《Spring Boot 源码学习系列》 上篇博文, Huazie 带大家从源码角度分析了 Spring Boot 内置的 http 编码功能,进一步熟悉了自动配置的装配流程。本篇趁热打铁,继续带大家分析 Spring Boot 内置的有关 Redis 的自动配置类【 RedisAutoConfiguration 】。 在开始本篇的内容介绍之前,我们先来

    2024年02月07日
    浏览(28)
  • 【Spring Boot 源码学习】自动装配流程源码解析(下)

    《Spring Boot 源码学习系列》 上篇博文,笔者带大家了解了自动装配流程中有关自动配置加载的流程; 本篇将介绍自动装配流程剩余的内容,包含了自动配置组件的排除和过滤、触发自动配置事件。 在开始本篇的内容介绍之前,我们先来看看往期的系列文章【有需要的朋友,

    2024年02月11日
    浏览(28)
  • 【Spring Boot 源码学习】自动装配流程源码解析(上)

    《Spring Boot 源码学习系列》 上篇博文,笔者带大家从整体上了解了AutoConfigurationImportSelector 自动装配逻辑的核心功能及流程,由于篇幅有限,更加细化的功能及流程详解还没有介绍。本篇开始将从其源码入手,重点解析细化后的自动装配流程源码。 在开始本篇的内容介绍之前

    2024年02月14日
    浏览(28)
  • 【Spring Boot 源码学习】走近 AutoConfigurationImportSelector

    《Spring Boot 源码学习系列》 上篇博文我们了解了 @EnableAutoConfiguration 注解,其中真正实现自动配置功能的核心实现者 AutoConfigurationImportSelector 还没有详细说明,本篇将从它的源码入手来重点介绍。 在介绍 AutoConfigurationImportSelector 之前,有必要了解下它所实现的 ImportSelector 接

    2024年02月12日
    浏览(23)
  • 【Spring Boot 源码学习】初识 SpringApplication

    《Spring Boot 源码学习系列》 往期的博文, Huazie 围绕 Spring Boot 的核心功能,带大家从总整体上了解 Spring Boot 自动配置的原理以及自动配置核心组件的运作过程。这些内容大家需要重点关注,只有了解这些基础的组件和功能,我们在后续集成其他三方类库的 Starters 时,才能够

    2024年02月05日
    浏览(31)
  • 【Spring Boot 源码学习】深入 FilteringSpringBootCondition

    Spring Boot 源码学习系列 前两篇博文笔者带大家从源码深入了解了 Spring Boot 的自动装配流程,其中自动配置过滤的实现由于篇幅限制,还未深入分析。 那么从本篇开始,Huazie 就带大家走近 AutoConfigurationImportFilter ,一起从源码解析 FilteringSpringBootCondition 、 OnBeanCondition 、 OnCl

    2024年02月09日
    浏览(30)
  • 【Spring Boot 源码学习】@Conditional 条件注解

    《Spring Boot 源码学习系列》 前面的博文,Huazie 带大家从 Spring Boot 源码深入了解了自动配置类的读取和筛选的过程,然后又详解了 OnClassCondition 、 OnBeanCondition 、 OnWebApplicationCondition 这三个自动配置过滤匹配子类实现。 在上述的博文中,我们其实已经初步涉及到了像 @Conditi

    2024年02月07日
    浏览(31)
  • 【Spring Boot 源码学习】BootstrapContext的实际使用场景

    《Spring Boot 源码学习系列》 上一篇博文《BootstrapRegistry 初始化器实现》, Huazie 向大家介绍了如何自定义 BootstrapRegistryInitializer 接口实现,并以此来执行自定义的初始化操作【如注册自定义的 Bean 、添加 BootstrapContext 关闭监听器】。其中涉及到了 BootstrapContext 的部分使用场景

    2024年03月11日
    浏览(36)
  • 【Spring Boot 源码学习】SpringApplication 的定制化介绍

    《Spring Boot 源码学习系列》 前面的博文, Huazie 带大家从 Spring Boot 的启动类 SpringApplication 上入手,了解了 SpringApplication 的实例化过程。这实例化构造过程中包含了各种初始化的操作,都是 Spring Boot 默认配置的。如果我们需要定制化配置, SpringApplication 也提供了相关的入口

    2024年01月25日
    浏览(27)
  • 【Spring Boot 源码学习】ConditionEvaluationReport 日志记录上下文初始化器

    《Spring Boot 源码学习系列》 上篇博文《共享 MetadataReaderFactory 上下文初始化器》, Huazie 带大家详细分析了 SharedMetadataReaderFactoryContextInitializer 。而在 spring-boot-autoconfigure 子模块中预置的上下文初始化器中,除了共享 MetadataReaderFactory 上下文初始化器,还有一个尚未分析。 那么

    2024年04月13日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包