目录

概述

EnableAutoConfiguration

ApplicationListener

RestartListener

BootstrapApplicationListener

创建bootstrap context

BootstrapImportSelectorConfiguration

BootstrapImportSelector

BootstrapConfiguration

PropertySourceBootstrapConfiguration

PropertyPlaceholderAutoConfiguration

ConfigurationPropertiesRebinderAutoConfiguration

EncryptionBootstrapConfiguration


概述

Spring cloud context是用户ApplicationContext的父级上下文,称呼为BootstrapContext。根据springboot的加载机制,很多第三方以及重要的Configuration配置均是保存在了spring.factories文件中。
spring-cloud-context模块下的对应文件如下:

# AutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
org.springframework.cloud.autoconfigure.LifecycleMvcEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.WritableEnvironmentEndpointAutoConfiguration
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.cloud.bootstrap.BootstrapApplicationListener,\
org.springframework.cloud.bootstrap.LoggingSystemShutdownListener,\
org.springframework.cloud.context.restart.RestartListener
# Bootstrap components
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration,\
org.springframework.cloud.bootstrap.encrypt.EncryptionBootstrapConfiguration,\
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration

主要包含:

  • EnableAutoConfiguration
  • ApplicationListener
  • BootstrapConfiguration

EnableAutoConfiguration

ApplicationListener

RestartListener

重启监听器,用于刷新上下文的。

@Overridepublic void onApplicationEvent(ApplicationEvent input) {if (input instanceof ApplicationPreparedEvent) {this.event = (ApplicationPreparedEvent) input;if (this.context == null) {this.context = this.event.getApplicationContext();}}// 上下文刷新结束事件,重新广播ApplicationPreparedEvent事件else if (input instanceof ContextRefreshedEvent) {if (this.context != null && input.getSource().equals(this.context)&& this.event != null) {this.context.publishEvent(this.event);}}else {if (this.context != null && input.getSource().equals(this.context)) {this.context = null;this.event = null;}}}

BootstrapApplicationListener

public class BootstrapApplicationListenerimplements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {/*** bootstrap 名称.*/public static final String BOOTSTRAP_PROPERTY_SOURCE_NAME = "bootstrap";/***顺序*/public static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 5;/*** 默认属性.*/public static final String DEFAULT_PROPERTIES = "springCloudDefaultProperties";private int order = DEFAULT_ORDER;
}    

用于响应ApplicationEnvironmentPreparedEvent,表明BootstrapContext的加载时机在Application context之前,且其加载顺序比ConfigFileApplicationListener超前。

    @Overridepublic void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {// 获取环境变量对象ConfigurableEnvironment environment = event.getEnvironment();// 读取spring.cloud.bootstrap.enabled环境属性,默认为true。可通过系统变量设置if (!environment.getProperty("spring.cloud.bootstrap.enabled", Boolean.class,true)) {return;}// don't listen to events in a bootstrap contextif (environment.getPropertySources().contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {return;}// 寻找当前环境是否已存在BootstrapContextConfigurableApplicationContext context = null;String configName = environment.resolvePlaceholders("${spring.cloud.bootstrap.name:bootstrap}");for (ApplicationContextInitializer<?> initializer : event.getSpringApplication().getInitializers()) {if (initializer instanceof ParentContextApplicationContextInitializer) {context = findBootstrapContext((ParentContextApplicationContextInitializer) initializer,configName);}}// 如果还没有被创建,则开始创建if (context == null) {context = bootstrapServiceContext(environment, event.getSpringApplication(),configName);// 注册 CloseContextOnFailureApplicationListenerevent.getSpringApplication().addListeners(new CloseContextOnFailureApplicationListener(context));}// BootstrapContext上的beanType为ApplicationContextInitializer类型的bean对象集合会被注册至用户的Context上apply(context, event.getSpringApplication(), environment);}

创建bootstrap context

private ConfigurableApplicationContext bootstrapServiceContext(ConfigurableEnvironment environment, final SpringApplication application,String configName) {//创建empty environmentStandardEnvironment bootstrapEnvironment = new StandardEnvironment();MutablePropertySources bootstrapProperties = bootstrapEnvironment.getPropertySources();for (PropertySource<?> source : bootstrapProperties) {bootstrapProperties.remove(source.getName());}// 读取spring.cloud.bootstrap.location属性,一般通过系统变量设置,默认为空String configLocation = environment.resolvePlaceholders("${spring.cloud.bootstrap.location:}");Map<String, Object> bootstrapMap = new HashMap<>();bootstrapMap.put("spring.config.name", configName);bootstrapMap.put("spring.main.web-application-type", "none");// 加载bootstrapContext配置文件的路径,与spring.config.name搭配使用if (StringUtils.hasText(configLocation)) {bootstrapMap.put("spring.config.location", configLocation);}bootstrapProperties.addFirst(new MapPropertySource(BOOTSTRAP_PROPERTY_SOURCE_NAME, bootstrapMap));把application context的 environment 的source 加入for (PropertySource<?> source : environment.getPropertySources()) {if (source instanceof StubPropertySource) {continue;}bootstrapProperties.addLast(source);}// TODO: is it possible or sensible to share a ResourceLoader?SpringApplicationBuilder builder = new SpringApplicationBuilder()// 此处activeProfiles是通过系统变量设置的.profiles(environment.getActiveProfiles()).bannerMode(Mode.OFF)// 应用bootstrap本身的环境变量.environment(bootstrapEnvironment)// Don't use the default properties in this builder.registerShutdownHook(false).logStartupInfo(false).web(WebApplicationType.NONE);final SpringApplication builderApplication = builder.application();// 配置入口函数类if (builderApplication.getMainApplicationClass() == null) {builder.main(application.getMainApplicationClass());}if (environment.getPropertySources().contains("refreshArgs")) {builderApplication.setListeners(filterListeners(builderApplication.getListeners()));}// 增加入口类BootstrapImportSelectorConfigurationbuilder.sources(BootstrapImportSelectorConfiguration.class);final ConfigurableApplicationContext context = builder.run();
、// 设置bootstrapContext的别名为bootstrapcontext.setId("bootstrap");// 配置bootstrapContext为用户Context的父类addAncestorInitializer(application, context);// 合并defaultProperties对应的变量至childEnvironmentbootstrapProperties.remove(BOOTSTRAP_PROPERTY_SOURCE_NAME);mergeDefaultProperties(environment.getPropertySources(), bootstrapProperties);return context;
}

BootstrapImportSelectorConfiguration

@Configuration(proxyBeanMethods = false)
@Import(BootstrapImportSelector.class)
public class BootstrapImportSelectorConfiguration {}

导入了BootstrapImportSelector

BootstrapImportSelector

public String[] selectImports(AnnotationMetadata annotationMetadata) {ClassLoader classLoader = Thread.currentThread().getContextClassLoader();// 加载 BootstrapConfiguration 对应的factoriesList<String> names = new ArrayList<>(SpringFactoriesLoader.loadFactoryNames(BootstrapConfiguration.class, classLoader));// 加载 spring.cloud.bootstrap.sources 设置的类names.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(this.environment.getProperty("spring.cloud.bootstrap.sources", ""))));List<OrderedAnnotatedElement> elements = new ArrayList<>();for (String name : names) {try {elements.add(new OrderedAnnotatedElement(this.metadataReaderFactory, name));}catch (IOException e) {continue;}}AnnotationAwareOrderComparator.sort(elements);String[] classNames = elements.stream().map(e -> e.name).toArray(String[]::new);return classNames;
}

上述的代码会去加载classpath路径下所有spring.factories文件中以org.springframework.cloud.bootstrap.BootstrapConfiguration作为Key的所有类;同时springcloud也支持通过设置spring.cloud.bootstrap.sources属性来加载指定类

spring.factories内容

# Bootstrap components
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration,\
org.springframework.cloud.bootstrap.encrypt.EncryptionBootstrapConfiguration,\
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration

BootstrapConfiguration

PropertySourceBootstrapConfiguration

配置源的加载,此Configuration主要用于确定是否外部加载的配置属性复写Spring内含的环境变量。注意其是ApplicationContextInitializer接口的实现类,前文已经提到,bootstrapContext上的此接口的bean类都会被注册至子级的SpringApplication对象上。

PropertyPlaceholderAutoConfiguration

ConfigurationPropertiesRebinderAutoConfiguration

@Configuration
@ConditionalOnBean(ConfigurationPropertiesBindingPostProcessor.class)
public class ConfigurationPropertiesRebinderAutoConfigurationimplements ApplicationContextAware, SmartInitializingSingleton {
}

EncryptionBootstrapConfiguration

Spring Cloud Context相关推荐

  1. Spring Cloud 参考文档(Spring Cloud Context:应用程序上下文服务)

    Spring Cloud Context:应用程序上下文服务 Spring Boot有一个关于如何使用Spring构建应用程序的观点,例如,它具有通用配置文件的常规位置,并具有用于通用管理和监控任务的 ...

  2. SpringCloud入门之应用程序上下文服务(Spring Cloud Context)详解

    构建分布式系统非常复杂且容易出错.Spring Cloud为最常见的分布式系统模式提供了简单易用的编程模型,帮助开发人员构建弹性,可靠和协调的应用程序.Spring Cloud构建于Spring Bo ...

  3. spring cloud连载第一篇之bootstrap context

    1. Spring Cloud Context: Application Context Services(应用上下文服务) 1.1 The Bootstrap Application Context ...

  4. Spring Cloud 覆写远端的配置属性

    覆写远端的配置属性 应用的配置源通常都是远端的Config Server服务器,默认情况下,本地的配置优先级低于远端配置仓库.如果想实现本地应用的系统变量和config文件覆盖远端仓库中的属性值,可以 ...

  5. Spring Cloud入门系列(1)- Spring生态体系发展史+全系框架介绍

    Spring发展史 2000年,Java EE和EJB迅速发展,很多知名公司都是采用此技术方案进行项目开发,但是EJB 属于重量级框架,开发繁琐.于是一个叫Rod Johnson的大佬写了一本叫做&l ...

  6. Spring Cloud Kubernetes 中文文档

    本参考指南介绍了如何使用Spring Cloud Kubernetes. 1.为什么需要Spring Cloud Kubernetes? Spring Cloud Kubernetes提供了使用Kub ...

  7. 《Spring Cloud 微服务架构进阶》读书笔记

    前页 随着 DevOps 和以 Docker 为主的容器技术的发展,云原生应用架构和微服 务变得流行起来. 云原生包含的内容很多,如 DevOps.持续交付.微服务.敏捷等 第一章,微服务架构介绍 架 ...

  8. 二、何为Spring Boot整合Spring Cloud?

    题语:学习方法之多思考:正向.逆向.跳跃 作者:A哥(YourBatman) wx号:fsx641385712(备注"Java群"字样) 公众号:BAT的乌托邦(ID:BAT-ut ...

  9. Spring Cloud教程(八)云原生应用程序

    Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线).分布式系统的协调导致了样板模式, 使用Spring Clo ...

最新文章

  1. linux 系统崩溃完全没有操作空间的系统修复
  2. 2016 实习招聘面试经历 - 3
  3. linux系统ip策略筛选器,在Linux下基于路由策略的IP地址控制
  4. 将扫描字符转换成点阵信息
  5. 一次误报引发的DNS检测方案的思考:DNS隧道检测平民解决方案
  6. OAM创始团队:揭秘OAMKubernetes实现核心原理
  7. c语言函数调用排序用插入法,C语言:编写查找和排序函数(二分查找,冒泡排序,选择排序法,插入排序)...
  8. python中字符串(str)的常用处理方法
  9. flutter 打开后闪退_vscode 扩展 pubspec 依赖快速打开文档
  10. 无法阻止的电竞热潮-用电竞连接世界
  11. PPT用宏插入不同背景图片
  12. 小爱音箱显示服务器连接不上,小爱音箱无法连接WiFi解决方法
  13. 关于电脑连不上WiFi,但可以连上网线的解决办法
  14. 【报告分享】2021小红书电商直播趋势报告-千瓜数据(附下载)
  15. 首批接入司法数据的网贷平台已拒贷3万余失信被执行人
  16. 有关weka的相关问题
  17. JDBC连接数据库6个步骤
  18. 考研数据结构——(查找)
  19. 192.168.1.198接口地址
  20. P,NP,NP-complete,NP-hard

热门文章

  1. 封装getByClass(JS获取class的方法封装为一个函数)
  2. Oracle PL/SQL 程序设计读书笔记 - 第14章 DML和事务管理
  3. Jdk1.8新特性(二)——lambda表达式(参数列表)-{}和函数式接口@FunctionalInterface
  4. golang刷Leetcode系列 --- 加1
  5. 如何调整Loadrunner中Vuser的数量限制
  6. 罗杰斯:做你喜欢的工作,你会变成个有钱人
  7. Salt Master外部Job Cache配置
  8. A English version for my blog start.
  9. 分区表学习一:分区表介绍
  10. 转载: Web 研发模式演变