学习目标

  • 复习 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> {@Overridepublic 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

动手关注一下微信公众号:AlanShelby 感谢~~

bootstrap 点击按钮刷新_Spring Cloud 中的 Bootstrap 上下文相关推荐

  1. bootstrap 点击按钮刷新_bootstrap table onRefresh刷新事件

    bootstrap table onRefresh刷新事件 bootstrap table刷新按钮事件,当然开启了showRefresh:"true"显示刷新按钮,用户点击刷新按钮 ...

  2. 点击按钮返回数组 ages 中所有元素都大于输入框指定数值的元素和 $set()

    返回数组 ages 中所有元素都大于输入框指定数值的元素: <body><p>点击按钮返回数组 ages 中所有元素都大于输入框指定数值的元素.</p> <p ...

  3. Bootstrap—点击按钮控制div隐藏和显示的切换(图文详情)

    Bootstrap-点击按钮控制div隐藏和显示的切换 第一步:bootstrap有一个open类用来控制隐藏和显示,动态获取open是true还是false,并且点击按钮让toggle的true和f ...

  4. jQuery 点击按钮刷新页面

    //页面加载时绑定按钮点击事件$(function () {$("#按钮id").click(function () {refresh();});});//点击按钮调用的方法fun ...

  5. 点击按钮刷新_Chrome扩展推荐:抢票太累?后台监视网页,页面自动刷新和提醒...

    出于某种原因,在使用浏览器时我们可能需要每隔一段时间刷新一下网页. 例如,在监视阅读量和评论,抢购新产品.演唱会门票.火车票,关注的作者更新文章,网站服务突然中断这些场景中,如果都采用手动刷新,那是相 ...

  6. Android中点击按钮获取string.xml中内容并弹窗提示

    场景 AndroidStudio跑起来第一个App时新手遇到的那些坑: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103797 ...

  7. eureka自我保护时间_spring cloud中微服务之间的调用以及eureka的自我保护机制详解...

    上篇讲了spring cloud注册中心及客户端的注册,所以这篇主要讲一下服务和服务之间是怎样调用的 基于上一篇的搭建我又自己搭建了一个客户端微服务: 所以现在有两个微服务,我们所实现的就是微服务1和 ...

  8. 点击按钮复制文本框中的内容

    下面是自己整理的简单例子 <!DOCTYPE html>   <html lang="en">   <head>       <meta ...

  9. bootstrap 点击图片放大查看_Spring Cloud 之 Bootstrap 配置

    学习目标 今天我们一起学习一下 Bootstrap 配置的相关知识,在学习目标中我已经列出了今天需要学习的知识点,第一个知识点为复习知识点,属于 Spring Boot 中的知识,这里我们既然讲到了配 ...

最新文章

  1. github pages_使用GitHub Pages和Lighthouse增强您的开发人员产品组合
  2. 用python内置函数算复杂度吗_番外篇: Python 面试感受
  3. Java基础知识强化83:System类之gc()方法(垃圾回收)以及和finalize()区别
  4. java小编程----最接近的三数之和
  5. Java堆空间,本机堆和内存问题
  6. 7个华为关于C语言的经典面试题
  7. 如何检测过时的Kubernetes API
  8. oracle 修改 回话数,Oracle命令--修改oracle回话数
  9. pytorch torch.nn.TransformerEncoderLayer
  10. python列表输出斐波那契数列_Python|运用列表求斐波那契数列
  11. 人工智能-baidu-aip语音识别(语音转文字)
  12. java表格选中事件_表格中删除选中的操作
  13. mysql关键字了解
  14. linux查询进程命令stap,linux systemtap, stap++使用
  15. CEO面试你时喜欢问的十六个问题
  16. 186.MultiAutoCompleteTextView
  17. 单端测序与双末端测序问题
  18. 信息化与信息化系统__无线__网络工程标准
  19. Selenium 自动化测试从0实战经验
  20. IOS 最右 注册 登录协议分析记录

热门文章

  1. fiddler基础入门
  2. python标准库之fnmatch,dis,timeit
  3. app软件测试是否强制升级_这些测试方法对于任何软件都必须是强制性的
  4. wordpress忘记登录密码,更改域名的办法。
  5. Stateflow历史节点的使用
  6. 那些年我们一起写过的Python爬虫
  7. Spark SQL 简介
  8. Python 正则表达式re模块的使用
  9. Python中的TCP的客户端UDP学习----第一篇博客
  10. 深度学习《CGAN新认识》