写于:2018-12-14 08:52:37

一、什么是上下文

在一篇文章中,文章的上下文就是通篇文章的语境。而程序中的上下文,可以理解为整个应用程序的环境。

不同语言,不同的应用场景,存在不同的上下文。
在java web开发中,从 servlet 中的 ServletContext 到 spring 中的 ApplicationContext 在到 spring cloud 的bootstrap。

上下文在程序运行中起到承上启下的作用,这些上下文存储了系统相关的一些初始化信息,比如配置信息等。而这些上下文在程序运行过程中都能够通过特定的方式被获取到,并作用于业务代码中。

二、The Bootstrap Application Context

官方文档介绍

A Spring Cloud application operates by creating a “bootstrap” context, which is a parent context for the main application.

根据官方文档可以知道 Spring Cloud 中引入了新的上下文 bootstrap , 且是 application 的父容器。

三、Bootstrap上下文的创建

3.1、Event-driven architecture

event-driven-architecture.png
wiki

Event-driven architecture (EDA), is a software architecture pattern promoting the production, detection, consumption of, and reaction to events.

粗略翻译

事件驱动架构 是一种通过对事件的发现和消费来提高生产的软件架构模式,

3.2、基于 Event-driven architecture 构建 bootstrap 上下文

Spring中的事件监听机制

Springframework 对于 Event-Driven architecture 有着广泛的应用,如:配置文件的加载等。

bootstrap 上下文 的构建也是基于 Event-Driven architecuture 来完成。

借助监听器 BootstrapApplicationListener,监听对象 ApplicationEnvironmentPreparedEvent,来完成Bootstrap 上下文 的构建。

源码追踪

BootstrapApplicationListener 属于 spring-cloud-context 依赖中的代码

UML 图如下:
04.png
⑤ EventPublishingRunListener#environmentPrepared 广播 ApplicationEnvironmentPreparedEvent

  1. public void environmentPrepared(ConfigurableEnvironment environment) {
  2. this.initialMulticaster.multicastEvent(
  3. new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
  4. }

四、Application Context Hierarchies

If you have a bootstrap.yml (or properties) then those properties are used to configure the Bootstrap context, 在 Spring Cloud 应用程序中,如果存在 bootstrap.yml(or properties) ,将优先使用 bootstrap 上下文中的配置属性。

通过实验验证 bootstrap 是 application 的父容器

4.1、借助spring-boot-actuator 模块验证

参考文章:Actuator应用监控

启动应用程序访问 /beans,结果如下
03.png

4.2、通过源码进行分析

01.png
通过代码我们可以知道在 执行 prepareEnvironment 环境准备的时候发送事件进行了 bootstrap 上下文的创建。

application 上下文的创建是在 IOC 容器创建的时候在加载的, 显而易见,bootstrap 的创建优先于 application。

五、bootstrap 最佳实践

Because of the ordering rules of property sources the “bootstrap” entries take precedence, but note that these do not contain any data from bootstrap.yml, which has very low precedence, but can be used to set defaults. 官方推荐我们使用 bootstrap 用来存放一些常用的默认不会变更的属性。

六、问题

先来看看 BootstrapApplicationListener#onApplicationEvent 相关代码

  1. public class BootstrapApplicationListener ......{
  2. @Override
  3. public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
  4. ConfigurableEnvironment environment = event.getEnvironment();
  5. // bootstrap 上下文的创建可以关闭
  6. if (!environment.getProperty("spring.cloud.bootstrap.enabled", Boolean.class,
  7. true)) {
  8. return;
  9. }
  10. ......
  11. }
  12. }

可以知道,再引入了 spring-cloud-context 依赖后,如果不想 bootstrap 上下文创建,可以通过配置参数 spring.cloud.bootstrap.enabled=false 来关闭。

6.1、application.properties 关闭 bootsrap 配置不生效

application.properties 中添加 spring.cloud.bootstrap.enabled=false 无法关闭 bootstrap 上下文的创建。

在执行 prepareEnvironment 环境准备的时候进行了 bootstrap 上下文的创建。而 application 上下文的创建是在 IOC 容器创建的时候在加载的, bootstrap 加载的优先级高于 application的加载顺序。所以在 application.properteis 配置关闭 bootsrap 上下文不生效。

6.2、关闭 bootstrap 上下文

那应该如何关闭 bootstrap 上下文:通过启动参数设置event-driven-architecture.png