SpringBoot配置文件优先级

一、SpringBoot 配置文件加载优先级

Spring Boot uses a very particular PropertySource order that is designed to allow sensible overriding of values. Properties are considered in the following order

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1. 开发者工具 Devtools 全局配置参数;  

2. 单元测试上的 [@TestPropertySource](mailto:@TestPropertySource)` 注解指定的参数;

3. 单元测试上的 [@SpringBootTest](mailto:@SpringBootTest)` 注解指定的参数;

4. 命令行指定的参数,如 java -jar springboot.jar --name="xxx";

5. 命令行中的 SPRING_APPLICATION_JSON 指定参数, 如 java -Dspring.application.json='{"name":"xxx"}' -jar springboot.jar

6. ServletConfig初始化参数;

7. ServletContext初始化参数;

8. JNDI参数(如 java:comp/env/spring.application.json);

9. Java系统参数(来源:System.getProperties());

10. 操作系统环境变量参数;

11. RandomValuePropertySource 随机数,仅匹配:ramdom.*;

12. JAR包外面的配置文件参数(application-{profile}.properties(YAML))

13. JAR包里面的配置文件参数(application-{profile}.properties(YAML))

14. JAR包外面的配置文件参数(application.properties(YAML))

15. JAR包里面的配置文件参数(application.properties(YAML))

16. @Configuration (mailto:@Configuration)配置文件上 @PropertySource(mailto:@PropertySource) 注解加载的参数;

17. 默认参数(通过 SpringApplication.setDefaultProperties 指定);

这里我们只对比常用的几个地方的配置优先级:

命令行参数 > JAR包外面的 application-{profile}.properties > JAR包内的 application-{profile}.properties > JAR包外的 application.properties > JAR包内的 application.properties

这样可能不太直观,而且有的项目会将 application.properties 文件放在config文件夹内,于是进一步对比了这两个位置的优先级,结果如下

SpringBoot 应用程序在启动时会遵循以下顺序进行加载配置文件

  1. 类路径下的配置文件
  2. 类路径内config子目录的配置文件
  3. 项目根目录下的配置文件
  4. 项目根目录下config子目录的配置文件
1
2
3
4
5
6
7
8
9
10
. project-sample  
├── config
│ ├── application.yml (4)
│ └── src/main/resources
| │ ├── application.yml (1)
| │ └── config
| | │ ├── application.yml (2)
├── application.yml (3)

注:src/main/resources下的配置文件在项目编译时,会放在target/classes下

启动时加载配置文件顺序:1 -> 2 -> 3 -> 4,优先级 4 > 3 > 2 > 1

注意:

  • 如果在IDEA中是多 module 项目,3 和 4 的位置是指的是项目根目录下的位置
  • 当 .properties 和 .yml 文件同时存在时,.properties会失效,.yml会起作用。

二、bootstrap.yml配置文件

SpringCloud 的项目中,我们常常会碰到另外一个配置文件 bootstrap.yml。这个配置文件主要是用于应用程序上下文的引导阶段,该配置文件的加载是在 application.yml 之前。

bootstrap.yml 和 application.yml 文件的区别可参考:What is the difference between putting a property on application.yml or bootstrap.yml in spring boot

在 SpringCloud 中有两种上下文,一种是 bootstrap, 另外一种是 application, bootstrap 是应用程序的父上下文。官方的原话是 A Spring Cloud application operates by creating a “bootstrap” context, which is a parent context for the main application

bootstrap.yml配置文件的使用场景:

  • 使用配置中心时,这时需要在bootstrap配置文件中添加连接到配置中心的信息,来加载外部配置中心的配置信息
  • 一些固定的不能被覆盖的属性
  • 一些加密/解密的信息

项目中 bootstrap.yml 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
spring:
application:
name:
profiles:
active: local
cloud:
nacos:
# 远程配置
config:
server-addr:
namespace:
group: ${spring.profiles.active}
file-extension: yml
# 服务发现
discovery:
server-addr:
namespace:
group: ${spring.profiles.active}

引入配置中心Nacos

首先我们需要明确的是在没有Nacos之前,Spring Boot加载配置文件的顺序是怎样的。

在没有 Nacos 之前,项目启动时,第一个加载的是 bootstrap.yml,其次是加载 application.yml。如果在 application.yml 中设置了 profile 属性,那么最后加载的就是对应激活的文件,如 application-dev.yml 或者 application-prod.yml。

无论如何,在 Spring 家族中 bootstrap.yml 拥有最高的优先级。

无Nacos情境下 Spring Boot 的启动过程:

1
启动-->读取bootstrap.yml配置文件(本地没有就加载默认的)-->读取项目本地配置文件application.yml-->创建Spring容器-->加载Bean

引入Nacos之后,上面的顺序会发生少许变化。

在加载bootstrap.yml完之后,Spring不再是去读取本地的application.yml配置文件,而是去读取Nacos的配置文件,之后才是本地的application.yml配置文件。

有Nacos情境下 Spring Boot 的启动过程:

1
启动-->读取bootstrap.yml配置文件(本地没有就加载默认的)-->读取Nacos的配置文件-->读取项目本地配置文件application.yml-->创建Spring容器-->加载Bean

可以通过在远程配置中心中做如下配置,设置本地配置覆盖远程配置:

1
2
3
4
5
6
7
8
9
10
spring:
cloud:
config:
# 是否允许本地配置覆盖远程配置
allow-override: true
# 是否一切以本地配置为准,默认false
override-none: false
# 系统环境变量或系统属性才能覆盖远程配置文件的配置
# 本地配置文件中配置优先级低于远程配置,默认true
override-system-properties: true
文章作者: GeYu
文章链接: https://nuistgy.github.io/2023/02/14/SpringBoot配置文件优先级/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Yu's Blog