Spring Cloud Config

Spring Cloud Config

application.yml 和 bootstrap.yml 区别

加载顺序

  • bootstrap.yml 先加载
  • application.yml 后加载

bootstrap.yml 用于应用程序上下文的引导阶段。
bootstrap.yml 由父 Spring ApplicationContext 加载。
父ApplicationContext被加载到使用application.yml 的之前

配置区别

bootstrap.yml 和 application.yml 都可以用来配置参数

  • bootstrap.yml 可以理解为系统级别的一些参数配置,这些参数一般是不会变动的。
  • application.yml 可以用来定义应用节级别的,如果搭配 spring-cloud-config 使用application.yml 里面定义的文件可以实现动态替换。
    使用Stpring Cloud Config Server时,应在bootstrap.yml 中指定:
  • spring.application.name
  • spring.cloud.config.server.git.url
  • 一些加密/解密信息

application 的加载原理

启动上下文

Spring Cloud 会创建一个Bootstrap Context,作为Spring应用的Application Context的父上下文。初始化的时候,Bootstrap Context 复制从外部源加载配置属性并解析配置。 这两个上下文共享一个从外部获取的Environment.Bootstrap属性有高优先级,默认情况下,它们不会被本地配置覆盖。Bootstrap contextApplication Context 有着不同的约定,所有新增了一个bootstrap.yml 文件,而不是使用application.yml。保证Bootstarp ContextApplication Context 配置的分离。

应用上下文层次结构

如果你通过 SpringApplicaion 或者 SpringApplicationBuilder创建一个Application Context,那么会为spring应用的Application Context 创建父上下文Bootstrap Context。在Spring里有个特性,子上下文会继承父类的property sources,会新增额外的property sources。额外的property sources 有:

  • “bootstrap”: 如果在Boostrap Context 扫描到PropertySourceLocator并且有属性,则会添加到CompositePropertySource.Spring Cloud COnfig 就是通过这种方式来添加属性,详情请查看源码 ConfigServicePropertySourceLocator
  • “applicationConfig:[classpath:bootstrap.yml]” (如果有 spring.profiles.active=production,则例如 applicationConfig:[classpath:/bootstrap.yml]#product): 如果你是用bootstrap.yml 来配置Bootstrap Context,他比application.yml 优先级别要低,它将添加到子上下文,作为Spring Boot 应用程序的一部分。

由于优先级规则,Bootstrap Context 不包含从Bootstrap.yml 来的数据,但可以用它作为默认设置。
你可以很容易的扩展任何你建立的上下文层次,可以使用它提供的接口,或者使用 SpringApplicationBuillder包含的方法(parent(),child(),sibling())。 Bootstrap Context 将是最高级别的父类。扩展的每一个Context都有自己的 bootstrap property source(有可能是空的)。扩展的每一个Context 都有不同 spring.application.name。 同一层层次的父子上下文原则上也有着不同的名称,因此,也会有不同的Config Server配置。子上下文的属性在相同名字的情况下将覆盖父上下文的属性。
注意:SpringApplicationBuilder允许共享Environment到所有层次,但是不是默认的。 因此,同级的兄弟上下文不在和父类共享一些东西的时候不一定有相同的profiles或者property sources。

修改Bootstrap属性配置

源码位置: BootstrapApplicationLister

1
2
3
4
5
6
String configName = environment.resolvePlaceholders("${spring.cloud.bootstrap.name:bootstrap}");
String configLocation = environment.resolvePlaceholders("${spring.cloud.bootstrap.location:}");
Map<String, Object> bootstrapMap = new HashMap<>();bootstrapMap.put("spring.config.name",configName);
if(StringUtils.hasText(configLocation)){
bootstrapMap.put("spring.config.location", configLocation);
}

bootstrap.yml 是有spring.cloud.bootstrap.name(默认:“bootstrap”) 或者 spring.cloud.bootstrap.location(默认空)。这些属性行为与spring.config.* 类似,通过它的Environment来配置引导ApplicationContext。如果有一个激活的profile(来源与 spring.profiles.active 或者 Environment 的Api构建),例如 bootstrap-development.properies 就是配置了 profile为development的配置文件。

覆盖远程属性

property sources 被bootstrap context添加到应用通常远程的方式,比如“Config Server”。默认情况下,本地的配置文件不能覆盖远程配置,但是可以通过启动命令参数来覆盖远程配置。如果需要本地文件覆盖远程文件,需要在远程配置文件里设置 spring.cloud.config.allowOverride=true(这个配置不能在本地被设置)。一旦设置了这个权限,你可以配置更加细粒度的配置来配置覆盖的方式。

1
2
spring.cloud.config.overrideNoe = true #覆盖任何本地属性
spring.cloud.config.overrideSystemProperties=false #仅仅系统属性和环境变量

源文件详见 PropertySourceBootstrapProperties

自定义启动配置

bootstrap context 是依赖 /META-INF/spring.factories 文件里面的 org.springframework.cloud.bootstrap.BootstrapConfiguration 条目下面,通过逗号分隔的Spring @Configuration 类来建立的配置。任何main application context 需要自动注入的Bean可以在这里通过这种方式获取。这也是 ApplicationContextInitializer 建立@Bean的方式。可以通过 @Order来更改初始化序列,默认是”last”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# spring-cloud-context-1.1.1.RELEASE.jar
# spring.factories
# AutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.LifecycleMvcEndpointAutoConfiguration

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.cloud.bootstrap.BootstrapApplicationListener,\
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.PropertyPlaceholderAutoConfiguration

你添加的自定义BootstrapConfiguration类没有错误的@ComponentScanned到你的主应用上下文,他们可能是不需要的。使用一个另外的包不被@ComponentScan或者@SpringBootApplication注解覆盖到。
bootstrap context 通过 spring.factories 的配置类初始化所有的Bean都会在SpringApplication启动前加入到它的上下文里去。

自定义引导配置来源: Bootstrap Property Sources

默认的property source 添加额外的配置是通过配置服务(Config Server),你也可以自定义添加 property soruce 通过实现 PropertySourceLocator 接口来添加。你可以使用它加配置属从不同的服务,数据库或者其他。
demo:

1
2
3
4
5
6
7
8
@Configuration
public class CustomPropertySourceLocator implements PropertySourceLocator {
@Override
public PropertySource<?> locate(Environment environment) {
return new MapPropertySource("customProperty",
Collections.<String, Object>singletonMap("property.from.sample.custom.source", "worked as intended"));
}
}

Environment 被 ApplicationContext建立,并传入 property sources(可能不同的profile有不同的属性),所以,你可以从Environment寻找找一些特别的属性。比如spring.application.name,它是默认的Config Server property source。
如果你建立了一个jar包,里面添加了一个 META-INF/spring.factories文件:org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator 。那么“CostomProperty” 的

参考资料

(SpringCloud入门之常用的配置文件 application.yml和 bootstrap.yml区别)[https://www.cnblogs.com/BlogNetSpace/p/8469033.html]

(Spring Boot)[https://docs.spring.io/spring-boot/docs/2.0.3.RELEASE/reference/htmlsingle/]

(Spring Boot)[https://github.com/spring-projects/spring-boot]