application.yml与bootstrap.yml的区别

一.简述

Spring Boot 默认支持 properties(.properties) 和 YAML(.yml .yaml ) 两种格式的配置文件,yml 和 properties 文件都属于配置文件,功能一样。

Spring Cloud 构建于 Spring Boot 之上,在 Spring Boot 中有两种上下文,一种是 bootstrap,另外一种是 application,下面列举这两种配置文件的区别

1.加载顺序
若application.yml 和bootstrap.yml 在同一目录下:bootstrap.yml 先加载 application.yml后加载

bootstrap.yml 用于应用程序上下文的引导阶段。bootstrap.yml 由父Spring ApplicationContext加载。

2.配置区别
bootstrap.yml 和 application.yml 都可以用来配置参数。

bootstrap.yml 用来程序引导时执行,应用于更加早期配置信息读取。可以理解成系统级别的一些参数配置,这些参数一般是不会变动的。一旦bootStrap.yml 被加载,则内容不会被覆盖。

application.yml 可以用来定义应用级别的, 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。

3.属性覆盖问题
启动上下文时,Spring Cloud 会创建一个 Bootstrap Context,作为 Spring 应用的 Application Context 的父上下文。

初始化的时候,Bootstrap Context 负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的 Environment。Bootstrap 属性有高优先级,默认情况下,它们不会被本地配置覆盖。

也就是说如果加载的 application.yml 的内容标签与 bootstrap 的标签一致,application 也不会覆盖 bootstrap,而 application.yml 里面的内容可以动态替换。

二、典型的应用场景如下:

  • 当使用 Spring Cloud Config Server 的时候,你应该在 bootstrap.yml 里面指定 spring.application.name 和 spring.cloud.config.server.git.uri
  • 和一些加密/解密的信息

技术上,bootstrap.yml 是被一个父级的 Spring ApplicationContext 加载的。这个父级的 Spring ApplicationContext是先加载的,在加载application.yml 的 ApplicationContext之前。

为何需要把 config server 的信息放在 bootstrap.yml 里?

当使用 Spring Cloud 的时候,配置信息一般是从 config server 加载的,为了取得配置信息(比如密码等),你需要一些提早的或引导配置。因此,把 config server 信息放在 bootstrap.yml,用来加载真正需要的配置信息。

三、高级使用场景

启动上下文

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

下面是一个例子: bootstrap.yml

spring:
 application:
  name: foo
  cloud:
  config:
  uri: ${SPRING_CONFIG_URI:http://localhost:8888}

推荐在bootstrap.yml or application.yml里面配置spring.application.name. 你可以通过设置spring.cloud.bootstrap.enabled=false来禁用bootstrap

应用上下文层次结构

如果你通过SpringApplication或者SpringApplicationBuilder创建一个Application Context,那么会为spring应用的Application Context创建父上下文Bootstrap Context。在Spring里有个特性,子上下文会继承父类的property sources and profiles ,所以main application context 相对于没有使用Spring Cloud Config,会新增额外的property sources。额外的property sources有:

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

由于优先级规则,Bootstrap Context不包含从bootstrap.yml来的数据,但是可以用它作为默认设置。

你可以很容易的扩展任何你建立的上下文层次,可以使用它提供的接口,或者使用SpringApplicationBuilder包含的方法(parent()child()sibling())。Bootstrap Context将是最高级别的父类。扩展的每一个Context都有有自己的bootstrap property source(有可能是空的)。扩展的每一个Context都有不同spring.application.name。同一层层次的父子上下文原则上也有一有不同的名称,因此,也会有不同的Config Server配置。子上下文的属性在相同名字的情况下将覆盖父上下文的属性。

注意SpringApplicationBuilder允许共享Environment到所有层次,但是不是默认的。因此,同级的兄弟上下文不在和父类共享一些东西的时候不一定有相同的profiles或者property sources

修改Bootstrap属性配置

源码位置BootstrapApplicationListener

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.properties 就是配置了profiledevelopment的配置文件.

覆盖远程属性

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

比如:

  • spring.cloud.config.overrideNone=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”。

# 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都会在SpingApplicatin启动前加入到它的上下文里去。

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

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

  • 下面是一个自定义的例子:

@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"));
}

EnvironmentApplicationContext建立,并传入property sources(可能不同个profile有不同的属性),所以,你可以从Environment寻找找一些特别的属性。比如spring.application.name,它是默认的Config Server property source

如果你建立了一个jar包,里面添加了一个META-INF/spring.factories文件:

org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator

那么,”customProperty“的PropertySource将会被包含到应用。

posted @ 2021-08-27 15:12  Chen洋  阅读(7244)  评论(0编辑  收藏  举报