likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 21

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

一、引言

二、主要内容

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

2.1 BootstrapRegistry

2.2 BootstrapRegistryInitializer

2.3 BootstrapRegistry 初始化器实现

2.3.1 定义 DemoBootstrapper

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

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

上述定义中,我们只是展示了一个空实现的类,其中的 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 接口,可以用来确保 多个监听同一事件的监听器 可以按照我们 预定的顺序执行

2.3.2 添加 DemoBootstrapper

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

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

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

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

org.springframework.boot.BootstrapRegistryInitializer=com.example.demo.DemoBootstrapper

三、总结

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

转载自:https://juejin.cn/post/7395147410211602441
评论
请登录