目 录CONTENT

文章目录

SpringCloud配置文件加载顺序与参数优先级详解

Administrator
2025-10-11 / 0 评论 / 0 点赞 / 7 阅读 / 0 字 / 正在检测是否收录...
温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

SpringCloud配置文件加载顺序与参数优先级详解

场景背景

在微服务架构中,配置管理变得更加复杂,特别是当使用Spring Cloud时。Spring Cloud引入了Bootstrap上下文的概念,用于在主应用上下文启动之前加载配置,这使得配置加载机制比单纯的Spring Boot更加复杂。本文通过实际运行和日志分析,深入解析Spring Cloud配置加载机制,帮助开发者掌握配置文件加载顺序和参数优先级。

⚠️ 本文基于 Spring Boot 2.7.0 和 Spring Cloud 2021.0.3(ConfigData 模型兼容层)进行实验验证。
从 Spring Cloud 2021.0 开始,Bootstrap 上下文默认禁用,若使用 ConfigData 模型,其功能由 spring.config.import 替代。
本文通过添加 spring-cloud-starter-bootstrap 人为启用旧模型,以便对比说明。

术语说明

在开始之前,我们先明确几个核心概念:

  • Bootstrap上下文:Spring Cloud引入的用于加载外部配置(如配置中心)的独立上下文,在主应用上下文之前启动
  • Application上下文:标准的Spring Boot应用上下文,用于加载本地配置文件
  • 配置控制参数:用于控制配置加载行为的参数,如 --spring.profiles.active--spring.config.location
  • 属性值参数:用于直接提供属性值的参数,如 --app.description="命令行参数"-Dapp.description="JVM系统属性"

配置加载机制概述

Spring Cloud配置加载分为两个阶段:

Bootstrap配置加载阶段

在Bootstrap阶段,Spring Cloud会加载所有以[bootstrap]为前缀的配置文件,用于初始化配置中心客户端等组件。

例如:当使用配置中心时,Bootstrap阶段会加载bootstrap.yml配置文件以连接配置中心。

Application配置加载阶段

在Application阶段,Spring Boot加载所有以[application]为前缀的配置文件,这个阶段在Bootstrap阶段之后执行。

例如:当使用命令行参数--spring.profiles.active=prod时,Spring Boot会在Application阶段确定需要加载application-prod.yml配置文件。

一、Spring Cloud配置加载的双阶段机制

Spring Cloud配置加载严格分为两个串行阶段:

  1. Bootstrap上下文阶段

    • 加载所有bootstrap相关文件(包括profile-specific)
    • 初始化配置中心客户端等组件
    • 为Application阶段提供基础配置
  2. Application上下文阶段

    • 加载所有application相关文件
    • 在Bootstrap上下文之后执行
    • 合并Bootstrap阶段的配置

这两个阶段独立执行,不会交叉或并发执行。

二、外部配置属性源加载顺序

Spring Cloud使用特定的PropertySource顺序,旨在允许合理地覆盖值。属性按以下顺序加载(加载顺序从先到后):

  1. 默认属性(通过SpringApplication.setDefaultProperties指定)
  2. @PropertySource注解在@Configuration类上定义的属性
  3. Bootstrap配置数据文件(如bootstrap.properties等)
  4. Application配置数据文件(如application.properties等)
  5. RandomValuePropertySource,只包含random.*属性
  6. Java系统属性(System.getProperties())
  7. 操作系统环境变量
  8. 来自java:comp/env的JNDI属性
  9. ServletContext初始化参数
  10. ServletConfig初始化参数
  11. SPRING_APPLICATION_JSON中的属性(环境变量或系统属性中内嵌的JSON)
  12. 命令行参数
  13. 测试属性(@SpringBootTest#properties属性等)

三、配置文件加载顺序与优先级

在配置文件加载方面,Spring Boot和Spring Cloud遵循特定的搜索顺序和优先级规则。

配置文件搜索位置

Spring Boot按以下顺序搜索配置文件:

加载顺序优先级位置类型
1最低classpath根目录内部配置
2classpath下的/config包内部配置
3当前目录外部配置
4最高当前目录下的/config子目录外部配置

这意味着外部配置文件(位于jar包外部)优先级高于内部配置文件(位于jar包内部)。

同一目录下不同格式配置文件的处理

在同一目录下,Spring Boot会加载所有格式的配置文件(.properties、.yml、.yaml),但它们的加载顺序如下:

加载顺序优先级文件格式说明
1最低.yamlYAML格式,最先加载,优先级最低
2.ymlYAML格式,加载顺序居中,优先级中等
3最高.propertiesProperties格式,最后加载,优先级最高

注意:同一目录下不同格式文件(.properties、.yml、.yaml)会按上述顺序加载,后加载的文件会覆盖前面的值。因此虽然加载顺序是.yaml > .yml > .properties,但优先级却是.properties > .yml > .yaml。

关键点

  • Bootstrap配置文件先于Application配置文件加载:Spring Cloud采用双阶段加载机制,Bootstrap上下文作为Application上下文的父上下文,会优先完成配置加载,然后才开始Application上下文的配置加载过程。

  • --spring.profiles.active等参数控制加载内容:这些参数在Bootstrap阶段就被解析,用于确定需要加载的Profile特定配置文件,影响后续Application阶段的配置加载范围。

  • 外部配置文件优先级高于jar包内配置文件:对于相同位置的配置文件,外部文件(如jar包同级目录)具有更高的优先级,会覆盖jar包内部的同名配置文件中的属性值。

  • 同一目录下config目录优先于根目录:在相同优先级位置(如都是外部配置或都是内部配置),config子目录中的配置文件优先级高于根目录中的同名配置文件。

  • 同一目录下不同格式配置文件加载顺序:.yaml > .yml > .properties(加载顺序),但覆盖优先级是.properties > .yml > .yaml:在同一目录下,Spring Boot会按顺序加载所有格式的配置文件,虽然.properties文件最后加载,但它的值会覆盖之前加载的.yml和.yaml文件中的同名属性,因此具有最高优先级。

四、实验设计与实现

实验环境搭建

  1. 创建Spring Boot + Spring Cloud项目
  2. 添加spring-cloud-starter-bootstrap依赖以启用Bootstrap上下文
  3. 在src/main/resources和外部目录下分别创建bootstrap和application配置文件
  4. 实现ConfigurationLoggingApplicationListener监听器,用于记录配置加载过程

实验文件:springcloud-demo.zip

实验一:验证默认加载顺序

java -Dfile.encoding=UTF-8 -jar demo.jar

配置加载顺序(按加载顺序从先到后):

 1. bootstrap                                          => app.description: null
 2. systemProperties                                   => app.description: null
 3. systemEnvironment                                  => app.description: null
 4. random                                             => app.description: null
 5. cachedrandom                                       => app.description: null
 6. springCloudClientHostInfo                          => app.description: null
 7. Config resource 'file [config\bootstrap.properties]' via location 'optional:file:./config/' => app.description: "外部config目录bootstrap.properties"
 8. Config resource 'file [config\bootstrap.yml]' via location 'optional:file:./config/' => app.description: "外部config目录bootstrap.yml"
 9. Config resource 'file [config\bootstrap.yaml]' via location 'optional:file:./config/' => app.description: "外部config目录bootstrap.yaml"
10. Config resource 'file [bootstrap.properties]' via location 'optional:file:./' => app.description: "外部根目录bootstrap.properties"
11. Config resource 'file [bootstrap.yml]' via location 'optional:file:./' => app.description: "外部根目录bootstrap.yml"
12. Config resource 'file [bootstrap.yaml]' via location 'optional:file:./' => app.description: "外部根目录bootstrap.yaml"
13. Config resource 'class path resource [config/bootstrap.properties]' via location 'optional:classpath:/config/' => app.description: "jar包内config/bootstrap.properties"
14. Config resource 'class path resource [config/bootstrap.yml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/bootstrap.yml"
15. Config resource 'class path resource [config/bootstrap.yaml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/bootstrap.yaml"
16. Config resource 'class path resource [bootstrap.properties]' via location 'optional:classpath:/' => app.description: "jar包内根目录bootstrap.properties"
17. Config resource 'class path resource [bootstrap.yml]' via location 'optional:classpath:/' => app.description: "jar包内根目录bootstrap.yml"
18. Config resource 'class path resource [bootstrap.yaml]' via location 'optional:classpath:/' => app.description: "jar包内根目录bootstrap.yaml"

最终生效的配置值:

app.description: 外部config目录bootstrap.properties
app.summary: null

接着是Application阶段的加载:

 1. servletConfigInitParams                            => app.description: null
 2. servletContextInitParams                           => app.description: null
 3. systemProperties                                   => app.description: null
 4. systemEnvironment                                  => app.description: null
 5. random                                             => app.description: null
 6. springCloudDefaultProperties                       => app.description: "外部config目录bootstrap.properties"
 7. cachedrandom                                       => app.description: null
 8. springCloudClientHostInfo                          => app.description: null
 9. Config resource 'file [config\application.properties]' via location 'optional:file:./config/' => app.description: "外部config目录application.properties"
                                                       => app.summary: "这是外部config目录的application.properties配置文件"
10. Config resource 'file [config\application.yml]' via location 'optional:file:./config/' => app.description: "外部config目录application.yml"
                                                       => app.summary: "这是外部config目录的application.yml配置文件"
11. Config resource 'file [config\application.yaml]' via location 'optional:file:./config/' => app.description: "外部config目录application.yaml"
                                                       => app.summary: "这是外部config目录的application.yaml配置文件"
12. Config resource 'file [application.properties]' via location 'optional:file:./' => app.description: "外部根目录application.properties"
                                                       => app.summary: "这是外部根目录的application.properties配置文件"
13. Config resource 'file [application.yml]' via location 'optional:file:./' => app.description: "外部根目录application.yml"
                                                       => app.summary: "这是外部根目录的application.yml配置文件"
14. Config resource 'file [application.yaml]' via location 'optional:file:./' => app.description: "外部根目录application.yaml"
                                                       => app.summary: "这是外部根目录的application.yaml配置文件"
15. Config resource 'class path resource [config/application.properties]' via location 'optional:classpath:/config/' => app.description: "jar包内config/application.properties"
                                                       => app.summary: "这是jar包内config目录的application.properties配置文件"
16. Config resource 'class path resource [config/application.yml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/application.yml"
                                                       => app.summary: "这是jar包内config目录的application.yml配置文件"
17. Config resource 'class path resource [config/application.yaml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/application.yaml"
                                                       => app.summary: "这是jar包内config目录的application.yaml配置文件"
18. Config resource 'class path resource [application.properties]' via location 'optional:classpath:/' => app.description: "jar包内根目录application.properties"
                                                       => app.summary: "这是jar包内根目录的application.properties配置文件"
19. Config resource 'class path resource [application.yml]' via location 'optional:classpath:/' => app.description: "jar包内根目录application.yml"
                                                       => app.summary: "这是jar包内根目录的application.yml配置文件"
20. Config resource 'class path resource [application.yaml]' via location 'optional:classpath:/' => app.description: "jar包内根目录application.yaml"
                                                       => app.summary: "这是jar包内根目录的application.yaml配置文件"

最终生效的配置值:

app.description: 外部config目录bootstrap.properties
app.summary: 这是外部config目录的application.properties配置文件

结论:

  1. Bootstrap配置文件先于Application配置文件加载
  2. jar包内的配置文件先被加载,但外部配置文件具有更高的优先级
  3. 同级目录下config目录优先于根目录
  4. 最终生效的是外部config目录的bootstrap.properties(注意:Bootstrap阶段加载的配置会传递给Application阶段)

实验二:验证 Profile 特定加载

java -Dfile.encoding=UTF-8 -jar demo.jar --spring.profiles.active=prod

配置加载顺序(按加载顺序从先到后):

 1. bootstrap                                          => app.description: null
 2. commandLineArgs                                    => app.description: null
 3. systemProperties                                   => app.description: null
 4. systemEnvironment                                  => app.description: null
 5. random                                             => app.description: null
 6. cachedrandom                                       => app.description: null
 7. springCloudClientHostInfo                          => app.description: null
 8. Config resource 'file [config\bootstrap-prod.properties]' via location 'optional:file:./config/' => app.description: "外部config目录bootstrap-prod.properties"
 9. Config resource 'file [config\bootstrap-prod.yml]' via location 'optional:file:./config/' => app.description: "外部config目录bootstrap-prod.yml"
10. Config resource 'file [config\bootstrap-prod.yaml]' via location 'optional:file:./config/' => app.description: "外部config目录bootstrap-prod.yaml"
11. Config resource 'file [bootstrap-prod.properties]' via location 'optional:file:./' => app.description: "外部根目录bootstrap-prod.properties"
12. Config resource 'file [bootstrap-prod.yml]' via location 'optional:file:./' => app.description: "外部根目录bootstrap-prod.yml"
13. Config resource 'file [bootstrap-prod.yaml]' via location 'optional:file:./' => app.description: "外部根目录bootstrap-prod.yaml"
14. Config resource 'file [config\bootstrap.properties]' via location 'optional:file:./config/' => app.description: "外部config目录bootstrap.properties"
15. Config resource 'file [config\bootstrap.yml]' via location 'optional:file:./config/' => app.description: "外部config目录bootstrap.yml"
16. Config resource 'file [config\bootstrap.yaml]' via location 'optional:file:./config/' => app.description: "外部config目录bootstrap.yaml"
17. Config resource 'file [bootstrap.properties]' via location 'optional:file:./' => app.description: "外部根目录bootstrap.properties"
18. Config resource 'file [bootstrap.yml]' via location 'optional:file:./' => app.description: "外部根目录bootstrap.yml"
19. Config resource 'file [bootstrap.yaml]' via location 'optional:file:./' => app.description: "外部根目录bootstrap.yaml"
20. Config resource 'class path resource [config/bootstrap-prod.properties]' via location 'optional:classpath:/config/' => app.description: "jar包内config/bootstrap-prod.properties"
21. Config resource 'class path resource [config/bootstrap-prod.yml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/bootstrap-prod.yml"
22. Config resource 'class path resource [config/bootstrap-prod.yaml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/bootstrap-prod.yaml"
23. Config resource 'class path resource [bootstrap-prod.properties]' via location 'optional:classpath:/' => app.description: "jar包内根目录bootstrap-prod.properties"
24. Config resource 'class path resource [bootstrap-prod.yml]' via location 'optional:classpath:/' => app.description: "jar包内根目录bootstrap-prod.yml"
25. Config resource 'class path resource [bootstrap-prod.yaml]' via location 'optional:classpath:/' => app.description: "jar包内根目录bootstrap-prod.yaml"
26. Config resource 'class path resource [config/bootstrap.properties]' via location 'optional:classpath:/config/' => app.description: "jar包内config/bootstrap.properties"
27. Config resource 'class path resource [config/bootstrap.yml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/bootstrap.yml"
28. Config resource 'class path resource [config/bootstrap.yaml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/bootstrap.yaml"
29. Config resource 'class path resource [bootstrap.properties]' via location 'optional:classpath:/' => app.description: "jar包内根目录bootstrap.properties"
30. Config resource 'class path resource [bootstrap.yml]' via location 'optional:classpath:/' => app.description: "jar包内根目录bootstrap.yml"
31. Config resource 'class path resource [bootstrap.yaml]' via location 'optional:classpath:/' => app.description: "jar包内根目录bootstrap.yaml"

最终生效的配置值:

app.description: 外部config目录bootstrap-prod.properties
app.summary: null

Application阶段加载:

 1. commandLineArgs                                    => app.description: null
 2. servletConfigInitParams                            => app.description: null
 3. servletContextInitParams                           => app.description: null
 4. systemProperties                                   => app.description: null
 5. systemEnvironment                                  => app.description: null
 6. random                                             => app.description: null
 7. springCloudDefaultProperties                       => app.description: "外部config目录bootstrap-prod.properties"
 8. cachedrandom                                       => app.description: null
 9. springCloudClientHostInfo                          => app.description: null
10. Config resource 'file [config\application-prod.properties]' via location 'optional:file:./config/' => app.description: "外部config目录application-prod.properties"
                                                       => app.summary: "这是外部config目录的application-prod.properties配置文件"
11. Config resource 'file [config\application-prod.yml]' via location 'optional:file:./config/' => app.description: "外部config目录application-prod.yml"
                                                       => app.summary: "这是外部config目录的application-prod.yml配置文件"
12. Config resource 'file [config\application-prod.yaml]' via location 'optional:file:./config/' => app.description: "外部config目录application-prod.yaml"
                                                       => app.summary: "这是外部config目录的application-prod.yaml配置文件"
13. Config resource 'file [application-prod.properties]' via location 'optional:file:./' => app.description: "外部根目录application-prod.properties"
                                                       => app.summary: "这是外部根目录的application-prod.properties配置文件"
14. Config resource 'file [application-prod.yml]' via location 'optional:file:./' => app.description: "外部根目录application-prod.yml"
                                                       => app.summary: "这是外部根目录的application-prod.yml配置文件"
15. Config resource 'file [application-prod.yaml]' via location 'optional:file:./' => app.description: "外部根目录application-prod.yaml"
                                                       => app.summary: "这是外部根目录的application-prod.yaml配置文件"
16. Config resource 'file [config\application.properties]' via location 'optional:file:./config/' => app.description: "外部config目录application.properties"
                                                       => app.summary: "这是外部config目录的application.properties配置文件"
17. Config resource 'file [config\application.yml]' via location 'optional:file:./config/' => app.description: "外部config目录application.yml"
                                                       => app.summary: "这是外部config目录的application.yml配置文件"
18. Config resource 'file [config\application.yaml]' via location 'optional:file:./config/' => app.description: "外部config目录application.yaml"
                                                       => app.summary: "这是外部config目录的application.yaml配置文件"
19. Config resource 'file [application.properties]' via location 'optional:file:./' => app.description: "外部根目录application.properties"
                                                       => app.summary: "这是外部根目录的application.properties配置文件"
20. Config resource 'file [application.yml]' via location 'optional:file:./' => app.description: "外部根目录application.yml"
                                                       => app.summary: "这是外部根目录的application.yml配置文件"
21. Config resource 'file [application.yaml]' via location 'optional:file:./' => app.description: "外部根目录application.yaml"
                                                       => app.summary: "这是外部根目录的application.yaml配置文件"
22. Config resource 'class path resource [config/application-prod.properties]' via location 'optional:classpath:/config/' => app.description: "jar包内config/application-prod.properties"
                                                       => app.summary: "这是jar包内config目录的application-prod.properties配置文件"
23. Config resource 'class path resource [config/application-prod.yml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/application-prod.yml"
                                                       => app.summary: "这是jar包内config目录的application-prod.yml配置文件"
24. Config resource 'class path resource [config/application-prod.yaml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/application-prod.yaml"
                                                       => app.summary: "这是jar包内config目录的application-prod.yaml配置文件"
25. Config resource 'class path resource [application-prod.properties]' via location 'optional:classpath:/' => app.description: "jar包内根目录application-prod.properties"
                                                       => app.summary: "这是jar包内根目录的application-prod.properties配置文件"
26. Config resource 'class path resource [application-prod.yml]' via location 'optional:classpath:/' => app.description: "jar包内根目录application-prod.yml"
                                                       => app.summary: "这是jar包内根目录的application-prod.yml配置文件"
27. Config resource 'class path resource [application-prod.yaml]' via location 'optional:classpath:/' => app.description: "jar包内根目录application-prod.yaml"
                                                       => app.summary: "这是jar包内根目录的application-prod.yaml配置文件"
28. Config resource 'class path resource [config/application.properties]' via location 'optional:classpath:/config/' => app.description: "jar包内config/application.properties"
                                                       => app.summary: "这是jar包内config目录的application.properties配置文件"
29. Config resource 'class path resource [config/application.yml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/application.yml"
                                                       => app.summary: "这是jar包内config目录的application.yml配置文件"
30. Config resource 'class path resource [config/application.yaml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/application.yaml"
                                                       => app.summary: "这是jar包内config目录的application.yaml配置文件"
31. Config resource 'class path resource [application.properties]' via location 'optional:classpath:/' => app.description: "jar包内根目录application.properties"
                                                       => app.summary: "这是jar包内根目录的application.properties配置文件"
32. Config resource 'class path resource [application.yml]' via location 'optional:classpath:/' => app.description: "jar包内根目录application.yml"
                                                       => app.summary: "这是jar包内根目录的application.yml配置文件"
33. Config resource 'class path resource [application.yaml]' via location 'optional:classpath:/' => app.description: "jar包内根目录application.yaml"
                                                       => app.summary: "这是jar包内根目录的application.yaml配置文件"

最终生效的配置值:

app.description: 外部config目录bootstrap-prod.properties
app.summary: 这是外部config目录的application-prod.properties配置文件

结论:

  1. Bootstrap配置文件先于Application配置文件加载
  2. --spring.profiles.active=prod会触发加载所有位置的*-prod.*配置文件
  3. jar包内的配置文件先被加载,但外部配置文件具有更高的优先级
  4. 同级目录下config目录优先于根目录
  5. 最终生效的是外部config目录的bootstrap-prod.properties

五、属性值参数加载顺序验证

实验三:命令行 vs JVM 参数 vs 环境变量

java -Dfile.encoding=UTF-8 -jar demo.jar --spring.profiles.active=prod --app.description="命令行参数配置"

配置加载顺序(按加载顺序从先到后):

 1. bootstrap                                          => app.description: null
 2. commandLineArgs                                    => app.description: "命令行参数配置"
 3. systemProperties                                   => app.description: null
 4. systemEnvironment                                  => app.description: null
 5. random                                             => app.description: null
 6. cachedrandom                                       => app.description: null
 7. springCloudClientHostInfo                          => app.description: null
 8. Config resource 'file [config\bootstrap-prod.properties]' via location 'optional:file:./config/' => app.description: "外部config目录bootstrap-prod.properties"
 9. Config resource 'file [config\bootstrap-prod.yml]' via location 'optional:file:./config/' => app.description: "外部config目录bootstrap-prod.yml"
10. Config resource 'file [config\bootstrap-prod.yaml]' via location 'optional:file:./config/' => app.description: "外部config目录bootstrap-prod.yaml"
11. Config resource 'file [bootstrap-prod.properties]' via location 'optional:file:./' => app.description: "外部根目录bootstrap-prod.properties"
12. Config resource 'file [bootstrap-prod.yml]' via location 'optional:file:./' => app.description: "外部根目录bootstrap-prod.yml"
13. Config resource 'file [bootstrap-prod.yaml]' via location 'optional:file:./' => app.description: "外部根目录bootstrap-prod.yaml"
14. Config resource 'file [config\bootstrap.properties]' via location 'optional:file:./config/' => app.description: "外部config目录bootstrap.properties"
15. Config resource 'file [config\bootstrap.yml]' via location 'optional:file:./config/' => app.description: "外部config目录bootstrap.yml"
16. Config resource 'file [config\bootstrap.yaml]' via location 'optional:file:./config/' => app.description: "外部config目录bootstrap.yaml"
17. Config resource 'file [bootstrap.properties]' via location 'optional:file:./' => app.description: "外部根目录bootstrap.properties"
18. Config resource 'file [bootstrap.yml]' via location 'optional:file:./' => app.description: "外部根目录bootstrap.yml"
19. Config resource 'file [bootstrap.yaml]' via location 'optional:file:./' => app.description: "外部根目录bootstrap.yaml"
20. Config resource 'class path resource [config/bootstrap-prod.properties]' via location 'optional:classpath:/config/' => app.description: "jar包内config/bootstrap-prod.properties"
21. Config resource 'class path resource [config/bootstrap-prod.yml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/bootstrap-prod.yml"
22. Config resource 'class path resource [config/bootstrap-prod.yaml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/bootstrap-prod.yaml"
23. Config resource 'class path resource [bootstrap-prod.properties]' via location 'optional:classpath:/' => app.description: "jar包内根目录bootstrap-prod.properties"
24. Config resource 'class path resource [bootstrap-prod.yml]' via location 'optional:classpath:/' => app.description: "jar包内根目录bootstrap-prod.yml"
25. Config resource 'class path resource [bootstrap-prod.yaml]' via location 'optional:classpath:/' => app.description: "jar包内根目录bootstrap-prod.yaml"
26. Config resource 'class path resource [config/bootstrap.properties]' via location 'optional:classpath:/config/' => app.description: "jar包内config/bootstrap.properties"
27. Config resource 'class path resource [config/bootstrap.yml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/bootstrap.yml"
28. Config resource 'class path resource [config/bootstrap.yaml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/bootstrap.yaml"
29. Config resource 'class path resource [bootstrap.properties]' via location 'optional:classpath:/' => app.description: "jar包内根目录bootstrap.properties"
30. Config resource 'class path resource [bootstrap.yml]' via location 'optional:classpath:/' => app.description: "jar包内根目录bootstrap.yml"
31. Config resource 'class path resource [bootstrap.yaml]' via location 'optional:classpath:/' => app.description: "jar包内根目录bootstrap.yaml"

最终生效的配置值:

app.description: 命令行参数配置
app.summary: null

Application阶段加载:

 1. commandLineArgs                                    => app.description: "命令行参数配置"
 2. servletConfigInitParams                            => app.description: null
 3. servletContextInitParams                           => app.description: null
 4. systemProperties                                   => app.description: null
 5. systemEnvironment                                  => app.description: null
 6. random                                             => app.description: null
 7. springCloudDefaultProperties                       => app.description: "外部config目录bootstrap-prod.properties"
 8. cachedrandom                                       => app.description: null
 9. springCloudClientHostInfo                          => app.description: null
10. Config resource 'file [config\application-prod.properties]' via location 'optional:file:./config/' => app.description: "外部config目录application-prod.properties"
                                                       => app.summary: "这是外部config目录的application-prod.properties配置文件"
11. Config resource 'file [config\application-prod.yml]' via location 'optional:file:./config/' => app.description: "外部config目录application-prod.yml"
                                                       => app.summary: "这是外部config目录的application-prod.yml配置文件"
12. Config resource 'file [config\application-prod.yaml]' via location 'optional:file:./config/' => app.description: "外部config目录application-prod.yaml"
                                                       => app.summary: "这是外部config目录的application-prod.yaml配置文件"
13. Config resource 'file [application-prod.properties]' via location 'optional:file:./' => app.description: "外部根目录application-prod.properties"
                                                       => app.summary: "这是外部根目录的application-prod.properties配置文件"
14. Config resource 'file [application-prod.yml]' via location 'optional:file:./' => app.description: "外部根目录application-prod.yml"
                                                       => app.summary: "这是外部根目录的application-prod.yml配置文件"
15. Config resource 'file [application-prod.yaml]' via location 'optional:file:./' => app.description: "外部根目录application-prod.yaml"
                                                       => app.summary: "这是外部根目录的application-prod.yaml配置文件"
16. Config resource 'file [config\application.properties]' via location 'optional:file:./config/' => app.description: "外部config目录application.properties"
                                                       => app.summary: "这是外部config目录的application.properties配置文件"
17. Config resource 'file [config\application.yml]' via location 'optional:file:./config/' => app.description: "外部config目录application.yml"
                                                       => app.summary: "这是外部config目录的application.yml配置文件"
18. Config resource 'file [config\application.yaml]' via location 'optional:file:./config/' => app.description: "外部config目录application.yaml"
                                                       => app.summary: "这是外部config目录的application.yaml配置文件"
19. Config resource 'file [application.properties]' via location 'optional:file:./' => app.description: "外部根目录application.properties"
                                                       => app.summary: "这是外部根目录的application.properties配置文件"
20. Config resource 'file [application.yml]' via location 'optional:file:./' => app.description: "外部根目录application.yml"
                                                       => app.summary: "这是外部根目录的application.yml配置文件"
21. Config resource 'file [application.yaml]' via location 'optional:file:./' => app.description: "外部根目录application.yaml"
                                                       => app.summary: "这是外部根目录的application.yaml配置文件"
22. Config resource 'class path resource [config/application-prod.properties]' via location 'optional:classpath:/config/' => app.description: "jar包内config/application-prod.properties"
                                                       => app.summary: "这是jar包内config目录的application-prod.properties配置文件"
23. Config resource 'class path resource [config/application-prod.yml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/application-prod.yml"
                                                       => app.summary: "这是jar包内config目录的application-prod.yml配置文件"
24. Config resource 'class path resource [config/application-prod.yaml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/application-prod.yaml"
                                                       => app.summary: "这是jar包内config目录的application-prod.yaml配置文件"
25. Config resource 'class path resource [application-prod.properties]' via location 'optional:classpath:/' => app.description: "jar包内根目录application-prod.properties"
                                                       => app.summary: "这是jar包内根目录的application-prod.properties配置文件"
26. Config resource 'class path resource [application-prod.yml]' via location 'optional:classpath:/' => app.description: "jar包内根目录application-prod.yml"
                                                       => app.summary: "这是jar包内根目录的application-prod.yml配置文件"
27. Config resource 'class path resource [application-prod.yaml]' via location 'optional:classpath:/' => app.description: "jar包内根目录application-prod.yaml"
                                                       => app.summary: "这是jar包内根目录的application-prod.yaml配置文件"
28. Config resource 'class path resource [config/application.properties]' via location 'optional:classpath:/config/' => app.description: "jar包内config/application.properties"
                                                       => app.summary: "这是jar包内config目录的application.properties配置文件"
29. Config resource 'class path resource [config/application.yml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/application.yml"
                                                       => app.summary: "这是jar包内config目录的application.yml配置文件"
30. Config resource 'class path resource [config/application.yaml]' via location 'optional:classpath:/config/' => app.description: "jar包内config/application.yaml"
                                                       => app.summary: "这是jar包内config目录的application.yaml配置文件"
31. Config resource 'class path resource [application.properties]' via location 'optional:classpath:/' => app.description: "jar包内根目录application.properties"
                                                       => app.summary: "这是jar包内根目录的application.properties配置文件"
32. Config resource 'class path resource [application.yml]' via location 'optional:classpath:/' => app.description: "jar包内根目录application.yml"
                                                       => app.summary: "这是jar包内根目录的application.yml配置文件"
33. Config resource 'class path resource [application.yaml]' via location 'optional:classpath:/' => app.description: "jar包内根目录application.yaml"
                                                       => app.summary: "这是jar包内根目录的application.yaml配置文件"

最终生效的配置值:

app.description: 命令行参数配置
app.summary: 这是外部config目录的application-prod.properties配置文件

结论:命令行参数 > JVM系统属性(-D参数) > 环境变量,符合官方文档定义的优先级顺序。

六、配置加载机制深入解析

Bootstrap与Application双阶段加载机制

在Spring Cloud中,配置加载严格分为两个串行阶段:

  1. Bootstrap上下文阶段

    • 加载所有bootstrap相关文件(包括profile-specific)
    • 初始化配置中心客户端等组件
    • 为Application阶段提供基础配置
  2. Application上下文阶段

    • 加载所有application相关文件
    • 在Bootstrap上下文之后执行
    • 合并Bootstrap阶段的配置

这两个阶段独立执行,不会交叉或并发执行。

为什么Bootstrap配置优先级高于Application配置?

这是很多开发者容易困惑的问题。虽然Bootstrap配置先被加载,Application配置后被加载,但最终Bootstrap配置的值却生效了。这是为什么呢?

关键在于理解Spring Cloud的设计理念:

  1. Bootstrap上下文是Application上下文的父上下文

    • Bootstrap上下文先创建并加载配置
    • Application上下文后创建,但它继承了Bootstrap上下文的所有配置
    • 这种父子关系使得Bootstrap配置成为Application配置的"默认值"
  2. 属性源加载顺序机制

    • Spring将所有配置源按照加载顺序排序,形成一个PropertySource列表
    • Bootstrap相关的配置源在排序中位置较高,具有更高的优先级
    • 即使Application配置后加载,它在优先级排序中仍然低于Bootstrap配置
  3. 设计目的

    • Bootstrap配置通常包含连接配置中心、加密解密等关键基础设施配置
    • 这些配置需要在Application上下文初始化之前就可用
    • 保证关键配置不会被普通的Application配置意外覆盖

文件加载顺序与覆盖机制

在Spring Cloud中,配置文件的加载遵循"后加载覆盖先加载"的原则。这意味着:

  1. 同一属性在多个配置文件中定义时,后加载的文件中的值会覆盖先加载的文件中的值
  2. 加载顺序按照优先级从低到高进行,优先级高的位置的文件会后加载

例如,在默认配置下:

  1. 首先加载classpath:/bootstrap.yaml (Bootstrap阶段,优先级较低)
  2. 然后加载classpath:/bootstrap.yml
  3. 接着加载classpath:/bootstrap.properties
  4. 然后加载classpath:/config/bootstrap.yaml
  5. 依此类推,最后加载file:./config/bootstrap.properties (Bootstrap阶段,优先级最高)
  6. 接着开始Application阶段,加载classpath:/application.yaml
  7. 依此类推,最后加载file:./config/application.properties (Application阶段,优先级最高)

如果app.description在所有这些文件中都有定义,最终生效的将是file:./config/application.properties中的值。但在我们的实验中,Bootstrap配置的优先级更高,所以最终值来自Bootstrap配置。

七、实践应用总结

场景推荐做法
外部配置中心接入使用bootstrap配置文件配置配置中心连接信息
多环境配置使用 --spring.profiles.active 切换
容器部署通过 --spring.config.location 或挂载 /config
敏感配置使用环境变量或命令行参数注入

八、核心原则总结

  1. Bootstrap配置优于Application配置
  2. 命令行参数最高优先级
  3. ⚠️ 外部配置优于内部配置
  4. 特定环境配置覆盖通用配置
  5. 同级目录下 config 优先
  6. 后加载覆盖先加载
  7. ⚠️ 加载与解析分离:Bootstrap和Application两个阶段
  8. 同一目录下配置文件格式加载顺序:.properties > .yml > .yaml(实现细节)

九、版本注意事项

Spring Boot 2.4+ 和 Spring Cloud 2020.x+ 采用全新的 ConfigData 加载机制,
原则一致但底层实现差异较大,建议阅读对应版本文档。
Bootstrap上下文在新版本中默认不启用,需要添加spring-cloud-starter-bootstrap依赖。

参考文档

  1. Spring Boot官方文档 - Externalized Configuration
  2. Spring Cloud官方文档 - Bootstrap Application Context
  3. Spring Boot Properties and Configuration
  4. Spring Framework - PropertySource
0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区