Spring Boot 的配置加载机制

1,413 阅读3分钟

本文已参与掘金创作者训练营第三期「话题写作」赛道,详情查看:掘力计划|创作者训练营第三期正在进行,「写」出个人影响力


为了让同一个 Spring Boot 可以在不同的环境下运行,Spring 允许开发者将配置以各种方式外部华。我们可以使用诸如属性文件、YAML 文件、命令行参数、系统环境变量等作为 Spring Boot 应用程序的配置源。

配置中的属性可以通过如下方式注入到 Bean 中:

  • @Value 注解的属性
  • Spring Framework 的 Environment 抽象
  • 通过 @ConfigurationProperties 绑定的结构化对象

Spring 通过特定的 PropertySource 优先级加载配置,并允许优先级高的配置覆盖优先级低的配置。

配置加载优先级

以下是 Spring 加载配置资源的优先级(从低到高):

  1. Spring Boot 的默认属性,通过 SpringApplication 类中的 setDefaultProperties 方法执行。
  2. @Configuration 类上的 @PropertySource 指定的配置来源。
  3. 属性配置文件。这个是最常用的配置来源,不同的配置文件也是存在优先级关系的。(见下文)
  4. 属性 random.* 中的 RandomValuePropertySource。比如 random.int 可以随机取一个 int 类型的随机值。
  5. 操作系统的环境变量。
  6. Java 系统属性 System.getProperties(),就是在 java -D 命令中指定的一些属性。
  7. java:comp/env 中的 JNDI 属性
  8. ServletContext 初始化参数
  9. ServletConfig 初始化参数
  10. SPRING_APPLICATION_JSON (环境变量和系统参数中的内联 JSON)中的属性,在 Spring 启动的时候会被解析并添加到 Environment 中。具体的配置方式有以下几种:
    1. SPRING_APPLICATION_JSON 作为一个环境变量。
    2. spring.application.json 作为系统属性,如 java -Dspring.application.json='{"name": "Tom"}' -jar app.jar
    3. spring.application.json 作为命令行参数,如 java -jar app.jar --spring.application.json='{"name": "Tom"}'
  11. 命令行参数,也是比较常用的配置来源之一,比如 --server.port=8888,Spring 会把指定的配置添加到 Environment 中,如果不希望将命令行属性添加进去,可以通过 SpringApplication.setAddCommandLineProperties(false) 禁用它们。
  12. 测试类的 @SpringBootTest 注解中的 properties 属性。
  13. 测试类的 @TestPropertySource 执行的配置来源。
  14. DevTools 的全局设置属性,当 DevTools 启用的时候会生效,在 $HOME/.config/spring-boot 目录下。

属性配置文件

在以上的第三点,提到了属性配置文件,这是开发者最常用的配置来源,每个 Spring Boot 应用中都会有大量的配置项在属性配置文件当中。属性配置文件之间也是有区分的,它们同样存在优先级数据,当同样的属性名配置了不同属性值的时候,优先级高的会覆盖优先级低的,以下顺序从低到高:

  • 打包进 jar 的 application.propertiesapplication.yaml 文件。
  • 打包进 jar 的 application-{profile}.propertiesapplication-{profile}.yaml 文件。
  • jar 之外的 application.propertiesapplication.yaml 文件。
  • jar 之外的 application-{profile}.propertiesapplication-{profile}.yaml 文件。

在这里,推荐在一个 Spring Boot 应用中保持一致的属性配置文件格式。如果同一个应用中同时存在 .properties.yaml 格式的属性配置文件,则 .properties 配置文件的优先级更高。

Spring 会从以下几个位置查找属性配置文件(优先级从低到高):

  • 类路径
  • 类路径下的 config
  • 当前目录
  • 当前目录的 config 目录
  • 当前目录的 config 目录下的直接子目录

如果不喜欢 application 这个配置文件的名字,可以手动指定:

java -jar app.jar --spring.config.name=myconfig

配置文件的位置也是可以指定的:

java -jar app.jar --spring.config.location=\
    optional:classpath:/myconfig.properties

上面的指令中,optional: 的意思是,指定的位置不一定存在这个文件。后面的配置文件路径,如果需要配置多个路径,使用 , 隔开即可。