Spring Cloud Context
目录
概述
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相关推荐
- Spring Cloud 参考文档(Spring Cloud Context:应用程序上下文服务)
Spring Cloud Context:应用程序上下文服务 Spring Boot有一个关于如何使用Spring构建应用程序的观点,例如,它具有通用配置文件的常规位置,并具有用于通用管理和监控任务的 ...
- SpringCloud入门之应用程序上下文服务(Spring Cloud Context)详解
构建分布式系统非常复杂且容易出错.Spring Cloud为最常见的分布式系统模式提供了简单易用的编程模型,帮助开发人员构建弹性,可靠和协调的应用程序.Spring Cloud构建于Spring Bo ...
- spring cloud连载第一篇之bootstrap context
1. Spring Cloud Context: Application Context Services(应用上下文服务) 1.1 The Bootstrap Application Context ...
- Spring Cloud 覆写远端的配置属性
覆写远端的配置属性 应用的配置源通常都是远端的Config Server服务器,默认情况下,本地的配置优先级低于远端配置仓库.如果想实现本地应用的系统变量和config文件覆盖远端仓库中的属性值,可以 ...
- Spring Cloud入门系列(1)- Spring生态体系发展史+全系框架介绍
Spring发展史 2000年,Java EE和EJB迅速发展,很多知名公司都是采用此技术方案进行项目开发,但是EJB 属于重量级框架,开发繁琐.于是一个叫Rod Johnson的大佬写了一本叫做&l ...
- Spring Cloud Kubernetes 中文文档
本参考指南介绍了如何使用Spring Cloud Kubernetes. 1.为什么需要Spring Cloud Kubernetes? Spring Cloud Kubernetes提供了使用Kub ...
- 《Spring Cloud 微服务架构进阶》读书笔记
前页 随着 DevOps 和以 Docker 为主的容器技术的发展,云原生应用架构和微服 务变得流行起来. 云原生包含的内容很多,如 DevOps.持续交付.微服务.敏捷等 第一章,微服务架构介绍 架 ...
- 二、何为Spring Boot整合Spring Cloud?
题语:学习方法之多思考:正向.逆向.跳跃 作者:A哥(YourBatman) wx号:fsx641385712(备注"Java群"字样) 公众号:BAT的乌托邦(ID:BAT-ut ...
- Spring Cloud教程(八)云原生应用程序
Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线).分布式系统的协调导致了样板模式, 使用Spring Clo ...
最新文章
- linux 系统崩溃完全没有操作空间的系统修复
- 2016 实习招聘面试经历 - 3
- linux系统ip策略筛选器,在Linux下基于路由策略的IP地址控制
- 将扫描字符转换成点阵信息
- 一次误报引发的DNS检测方案的思考:DNS隧道检测平民解决方案
- OAM创始团队:揭秘OAMKubernetes实现核心原理
- c语言函数调用排序用插入法,C语言:编写查找和排序函数(二分查找,冒泡排序,选择排序法,插入排序)...
- python中字符串(str)的常用处理方法
- flutter 打开后闪退_vscode 扩展 pubspec 依赖快速打开文档
- 无法阻止的电竞热潮-用电竞连接世界
- PPT用宏插入不同背景图片
- 小爱音箱显示服务器连接不上,小爱音箱无法连接WiFi解决方法
- 关于电脑连不上WiFi,但可以连上网线的解决办法
- 【报告分享】2021小红书电商直播趋势报告-千瓜数据(附下载)
- 首批接入司法数据的网贷平台已拒贷3万余失信被执行人
- 有关weka的相关问题
- JDBC连接数据库6个步骤
- 考研数据结构——(查找)
- 192.168.1.198接口地址
- P,NP,NP-complete,NP-hard
热门文章
- 封装getByClass(JS获取class的方法封装为一个函数)
- Oracle PL/SQL 程序设计读书笔记 - 第14章 DML和事务管理
- Jdk1.8新特性(二)——lambda表达式(参数列表)-{}和函数式接口@FunctionalInterface
- golang刷Leetcode系列 --- 加1
- 如何调整Loadrunner中Vuser的数量限制
- 罗杰斯:做你喜欢的工作,你会变成个有钱人
- Salt Master外部Job Cache配置
- A English version for my blog start.
- 分区表学习一:分区表介绍
- 转载: Web 研发模式演变