Spring Boot 的配置文件优先级
公司 Config Server 的逻辑越来越复杂了,新同事很难确定多个配置文件的关系和优先级。由于 Spring Cloud Config 是通过创建一个临时的 Spring Boot Application 加载配置文件,完全复用了 Spring Boot 本身的逻辑,于是写了这篇文章介绍一下 Spring Boot 中配置文件的优先级。
一个真实的栗子
那么,Spring Cloud Config 究竟会配置多么复杂的规则呢?举一个真实的栗子:
1 | spring: |
上面是 Spring Cloud Config Server 的配置,它做了两个特殊的配置:
- 通过设置
pattern
将不同的应用映射到不同的配置仓库,实现应用间的配置独立管理。 - 通过
searchPaths
设置配置文件所在的文件夹,在默认情况 Config Server 只会搜索根目录下的配置文件,而上面的设置可以搜索/
、common
以及和应用同名的文件夹。
而请求配置时可以传入 application
、profile
和 label
三个动态配置,例如:
1 | # application/profile/label(optional) |
配置文件的匹配规则
这个请求会匹配到哪些配置文件呢?
在此首先忽略 label
,因为在大部分情况下它只和 git 所使用的分支有关,所以它不涉及到具体配置文件的匹配。
在 Spring Boot 中,配置文件的搜索条件主要由三个参数组成:
spring.config.name
:应用的名称,默认是application
(常量)加上spring.application.name
的值,在 Spring Cloud Config 中对应请求的application
。spring.profiles.active
:当前生效的 profile,在 Spring Cloud Config 中对应请求的profile
spring.config.location
:搜索配置文件的路径,在 Spring Cloud Config 对应配置文件中的searchPaths
Spring Cloud Config 本质是通过创建了一个临时的 Spring Boot Application,设置这些配置并复用 Spring Boot 的逻辑加载对应的配置文件。所以上面的请求最终的结果集为搜索路径 ['./', '/common', '/user-api']
乘以应用名 ['application', 'user-api']
乘以环境 ['', 'production', 'beta']
,共计 18 个配置文件,也就是:
1 | ./application.yml |
配置文件的优先级
那么这些配置文件中的优先级是什么样呢?
Spring Boot 严格按照以下顺序进行排序:
- profile
- location
- application
其中定义了多个 profile 和 location 时,越靠后的优先级越高,所以 beta
的优先级要大于 production
,./user-api
的优先级要大于 ./common
。
所以最终的优先级为:
1 | # profile/location/application 均为最高 |
源码解析
因为源码实现比较多而且绕,就不在这里大段的贴代码了,基本上只需要关注两处:
- Spring Cloud Config 复用 Spring Boot 逻辑加载配置文件的实现可以看
NativeEnvironmentRepository#findOne
。 - Spring Boot 加载配置文件的实现可以看
ConfigFileApplicationListener.Loader#load
。
更改优先级
默认情况 Spring Cloud Config 的配置会覆盖掉所有本地配置,包括命令行参数和环境变量,不过可以通过以下配置修改:
1 | spring: |
注意这些配置本身必须放在 Spring Cloud Config 中才会生效。