Spring Cloud 中的 Bootstrap 上下文

  • 复习 Spring 事件/监听器模式(ApplicationEvent / ApplicationListener)
  • 理解 Bootstrap 上下文
  • 理解 Spring Boot / Spring Cloud 上下文层次关系
    • 父子关系
    • BootstrapApplicationListener 是何时加载进来的
    • 为什么 Spring Cloud 上下文要比 Spring Boot 的上下文加载的早

一、复习 Spring 事件/监听器模式(ApplicationEvent / ApplicationListener)

对于 Spring 的事件/监听器模式,我们都已经很熟悉了,为了让我们更好的理解 Bootstrap 上下文,我们先来把 Spring 的基础知识通过一个小例子来回顾一下。
首先我们先创建项目:打开 https://start.spring.io/,填写相关信息,添加 Web、Actuator 以及 Cloud Bootstrap 依赖,点击 “Generate Project” 按钮生成项目,并导入到 idea 中。(注:此处使用的 Spring Boot 版本为 1.X 系列)

其次,我们使用 AnnotationConfigApplicationContext 来获取 Spring Boot 的上下文

 

/**
 * Spring事件/监听模式 demo
 *
 * @ClassName SpringEventListenerDemo
 * @Author AlanShelby
 * @Date 2019-04-18 14:59:33 14:59
 * @Version 1.0
 */
public class SpringEventListenerDemo {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

        // 增加监听器
        context.addApplicationListener(new MyApplicationListener());
        // 上下文启动
        context.refresh();
        // 发布事件
        context.publishEvent(new MyApplicationEvent("Hello World"));
        context.publishEvent(new MyApplicationEvent("Hello AlanShelby"));
        context.publishEvent(new MyApplicationEvent("Hello SpringCloud"));
    }

    /**
     * 自定义监听器
     *
     * @ClassName MyApplicationListener
     * @Author AlanShelby
     * @Date 2019/4/18 0018 15:35
     * @Version 1.0
     */
    private static class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {

        @Override
        public void onApplicationEvent(MyApplicationEvent event) {

            System.out.printf("MyApplicationListener receives event source : %s \n", event.getSource());
        }
    }

    /**
     * 自定义事件
     *
     * @ClassName MyApplicationEvent
     * @Author AlanShelby
     * @Date 2019/4/18 0018 15:36
     * @Version 1.0
     */
    private static class MyApplicationEvent extends ApplicationEvent {

        public MyApplicationEvent(Object source) {
            super(source);
        }
    }
}

以上是一个简单的 demo,demo 虽小,但是已经可以演示出 Spring 事件/监听器模式的基本特性了,起到一个引导作用。


二、理解 Bootstrap 上下文(结论

Bootstrap 上下文是 Spring Cloud 新引入的,与传统 Spring 上下文相同,即 ConfigurableApplicationContext 实例,由 BootstrapApplicationListener 监听 ApplicationEnvironmentPreparedEvent 事件时创建。


三、理解 Spring Boot / Spring Cloud 上下文层次关系

理解了什么是 Bootstrap 上下文,接下来我们就来分析一下 Spring Boot / Spring Cloud 上下文层次关系,这里我先把结论给出,然后一步步分析并推导出结论。

  • Spring Boot 上下文:
    • 非 Web 应用:AnnotationConfigApplicationContext
    • Web 应用:AnnotationConfigEmbeddedWebApplicationContext
  • Spring Cloud 上下文:Bootstrap(父)
    Spring Boot 上下文的两种情况,可在下图所示的断点出调试查看,此处就不再展开叙述。

1、父子关系

在创建项目的时候,我们引入的 Actuator 依赖在这里就能够发挥到作用了。为了方便演示,我们先在配置文件中关闭安全配置。

management.security.enabled=false

然后启动项目,访问 http://localhost:8080/beans,出现如下信息,显示 application 的 parent 是 bootstrap。

那既然他们之间存在父子关系,那么这个父子关系又是在什么地方设置的呢?这里我们就要从 ConfigurableApplicationContext 下手,在上面的文章中我们也说到了,ConfigurableApplicationContext 可以对应用上下文进行配置,一说到“可配置”,就要想到各种 setXX() 方法了,这里我们使用快捷键,在该类中查找类似方法。

不出我所料,我们找到了一个 setParent() 方法,Set the parent of this application context. 看到这句注释就很清晰了。

 

2、BootstrapApplicationListener 是何时加载进来的

 

 

上面我们了解了 Spring Boot / Spring Cloud 上下文之间的父子关系,那么 BootstrapApplicationListener 是何时进行加载的呢?这里我们在 idea 中打开这个类,在类名上右击选择 “Find Usages”,在结果中找到 spring.factories,如下图所示:

 

这个文件对于熟悉 Spring Boot 的人来说并不陌生, Spring Boot 中的 spring.factories 定义了一系列的 ApplicationListener 和 ApplicationContextInitializer 等其他系统所要的类。

我们都知道,Spring Boot 的项目默认启动类中的启动方法使这样写的:

SpringApplication.run(SpringCloudChapter1Application.class, args);

其实我们可以进行改造一下,变成下面的样子:

SpringApplication springApplication = new SpringApplication(SpringCloudChapter1Application.class);
springApplication.setWebEnvironment(true);
springApplication.run(args);

 

 

进入 new SpringApplication() -> initialize() 方法,下图中标红代码就是获取 spring.factories 文件中 ApplicationListener 和 ApplicationContextInitializer 的相应实现类,具体是通过SpringFactoriesLoader 类来实现的。如下图所示,这里就不再对如何查找的源码进行一一展示了。

3、为什么 Spring Cloud 上下文要比 Spring Boot 的上下文加载的早

要想弄明白这个问题,还是有一些难度的,下面我们一步步的进行分析。
首先我们先打开 BootstrapApplicationListener 这个类,可以发现,该类实现了 Ordered 接口,从下图可以看出,该类的加载优先级为最高优先级 + 5,也就是第六个加载,这排名已经比较靠前了。

虽然 BootstrapApplicationListener 是倒数第六个加载,比较靠前,但是并不能看出他比 Spring Boot 的上下文加载的早,所以我们还要进一步进行分析。
接下来我们还是要从启动类入手,找到 springApplication 类的 run() 方法,代码如下:

这里的 prepareEnvironment 应该引起你的注意,prepareEnvironment 会激发 ApplicationEnvironmentPreparedEvent 事件,而 ApplicationEnvironmentPreparedEvent 则会被 BootstrapApplicationListener 监听到,所以在此处,BootstrapApplicationListener 就已经被加载了,而 Spring Boot 的上下文则是在 context = createApplicationContext(); 处创建的,所以Spring Cloud 上下文要比 Spring Boot 的上下文加载的早。

 


至此,关于 Spring Cloud 中的 Bootstrap 上下文就讲解完了,这是我的理解,各位看官如果有不同见解或文章中有错误,请不吝指正。
所用代码码云地址:https://gitee.com/AlanShelby/spring-cloud-chapter
知乎专栏地址:https://zhuanlan.zhihu.com/c_200981602



作者:AlanShelby
链接:https://www.jianshu.com/p/385fd5ee9c0d
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 在面试Spring Boot 和 Spring Cloud 是两个常见的考点。Spring Boot 是一个用于简化 Spring 应用程序开发的框架,它提供了大量的开箱即用的 Starter,使得开发人员可以快速搭建和部署应用程序。在面试,面试官可能会问到你对 Spring Boot 的理解、使用经验以及它的重要性。你可以引用\[1\]提到的 Spring Boot 的重要性和广泛应用的情况来回答这个问题。 另外,面试也经常会涉及到 Spring CloudSpring Cloud 是一个用于构建分布式系统的框架,它基于 Spring Boot 提供了一系列的工具和组件,用于实现微服务架构。在面试,面试官可能会问到你对 Spring Cloud 的了解、使用经验以及它的优势。你可以引用\[2\]提到的 Spring Boot 和微服务的普及情况来回答这个问题。 此外,还有一个与 Spring Boot 和 Spring Cloud 相关的考点是 bootstrap.properties 文件。这个文件在应用程序上下文的引导阶段生效,一般在 Spring Cloud Config 或者 Nacos 使用。你可以引用\[3\]提到的 bootstrap.properties 的加载顺序和使用场景来回答这个问题。 总之,在面试,面试官可能会问到关于 Spring Boot 和 Spring Cloud 的问题,你可以根据自己的经验和引用的内容来回答这些问题。 #### 引用[.reference_title] - *1* *2* *3* [面试必须掌握的15道《Spring Boot 高频面试题》](https://blog.csdn.net/m0_62051288/article/details/126906412)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值