likes
comments
collection
share

【Spring Boot 源码学习】BootstrapContext的实际使用场景

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

【Spring Boot 源码学习】BootstrapContext的实际使用场景

一、引言

二、主要内容

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

2.1 BootstrapContext

2.2 BootstrapRegistry 初始化器实现

在开始讲解 BootstrapContext 的实际使用场景之前,我们需要首先通过 BootstrapRegistry 初始化器实现类 注册自定义的对象,以便后续在实际的场景中通过 BootstrapContext 来获取。

2.3 BootstrapContext 的实际使用场景

首先我们需要通过源码来明确下需要 添加哪些内容,哪些场景和引导上下文有关?

先来看如下的截图【SpringApplication##run】:

【Spring Boot 源码学习】BootstrapContext的实际使用场景

从上面可以看到 BootstrapContext 实际上有 3 处使用场景,分别是:

  • 早期启动时
  • 环境配置准备完成时
  • 应用上下文准备完成后关闭 BootstrapContext

2.3.1 早期启动时

首先我们来看看 早期启动时 的源码截图:

【Spring Boot 源码学习】BootstrapContext的实际使用场景 【Spring Boot 源码学习】BootstrapContext的实际使用场景 【Spring Boot 源码学习】BootstrapContext的实际使用场景

从上述截图可知,这里多播了 ApplicationStartingEvent 事件,我们如果想要监听这个事件,只需要实现对应的事件监听器,并添加到监听器列表 listeners 中即可。

下面我们来自定义有关 ApplicationStartingEvent 事件的监听器类:

public class DemoStartingListener implements ApplicationListener<ApplicationStartingEvent>, Ordered {

    @Override
    public void onApplicationEvent(ApplicationStartingEvent event) {
        ConfigurableBootstrapContext bootstrapContext = event.getBootstrapContext();
        User user = bootstrapContext.get(User.class);
        System.out.println("启动时获取User:" + user);
        user.setName("Huazie_1");
        user.setAge(19);
    }

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

上述代码中的 User 类只是一个简单的 POJO 对象,这里源码就不列出来了,可以自行定义即可。

那么上述自定义的监听器该如何添加到监听器列表 listeners 中呢?

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

有关监听器实现 Ordered 接口,这里再次提及下:它可以用来确保多个监听同一事件的监听器可以按照我们预定的顺序执行。

2.3.2 环境配置准备完成时

接着,我们来看看 准备环境配置 的源码截图:

【Spring Boot 源码学习】BootstrapContext的实际使用场景 【Spring Boot 源码学习】BootstrapContext的实际使用场景 【Spring Boot 源码学习】BootstrapContext的实际使用场景 【Spring Boot 源码学习】BootstrapContext的实际使用场景

从上述截图可知,这里显然在环境配置准备完成之后,多播了 ApplicationEnvironmentPreparedEvent 事件,我们如果想要监听这个事件,只需要实现对应的事件监听器,并添加到监听器列表 listeners 中即可。

下面我们来自定义有关 ApplicationEnvironmentPreparedEvent 事件的监听器类:

public class DemoEnvironmentPreparedListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
    @Override
    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
        ConfigurableBootstrapContext bootstrapContext = event.getBootstrapContext();
        if (bootstrapContext.isRegistered(User.class)) {
            User user = bootstrapContext.get(User.class);
            System.out.println("环境准备时获取User:" + user);
            user.setName("Huazie_2");
            user.setAge(20);
        }
    }

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

至于该监听器如何添加到监听器列表 listeners 中,显然跟 2.3.1 中的 DemoStartingListener 一样,等下会通过 SpringApplication 进行添加演示。

2.3.3 应用上下文准备完成后关闭 BootstrapContext

最后,我们看看准备应用上下文的源码截图:

【Spring Boot 源码学习】BootstrapContext的实际使用场景 【Spring Boot 源码学习】BootstrapContext的实际使用场景

2.4 实际使用演示

BootstrapContext 的实际使用场景已经在 2.3 中介绍,下面 Huazie 就带大家实操下。

首先,Spring Boot 启动类中需要修改如下:

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(DemoApplication.class);
        // 关闭 Banner打印
        springApplication.setBannerMode(Banner.Mode.OFF);
        // 添加 BootstrapRegistry初始化器实现
        springApplication.addBootstrapRegistryInitializer(new DemoBootstrapper());
        // 添加 监听器实现
        springApplication.addListeners(new DemoStartingListener(), new DemoEnvironmentPreparedListener());
        springApplication.run(args);
    }
}

修改好启动类的代码,我们就可以来运行了,如下截图:

【Spring Boot 源码学习】BootstrapContext的实际使用场景 从上述截图中,我们可以看到 2.3 中介绍的 3 个实际使用场景,已经全部打印日志信息了,说明定义的监听器已经执行了。

三、总结

本篇 Huazie 通过介绍 BootstrapContext 的实际使用场景,并演示了引导上下文在这些场景的实际使用,加深了大家对于 Spring Boot 的启动引导过程的了解,为后续的源码分析打下基础。

后续的博文,Huazie 就将从 SpringApplicationrun 方法入手,开始介绍 Spring Boot 的运行流程,敬请期待!

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