本文已参与掘金创作者训练营第三期「话题写作」赛道,详情查看:掘力计划|创作者训练营第三期正在进行,「写」出个人影响力。
为了让同一个 Spring Boot 可以在不同的环境下运行,Spring 允许开发者将配置以各种方式外部华。我们可以使用诸如属性文件、YAML 文件、命令行参数、系统环境变量等作为 Spring Boot 应用程序的配置源。
配置中的属性可以通过如下方式注入到 Bean 中:
@Value注解的属性- Spring Framework 的
Environment抽象 - 通过
@ConfigurationProperties绑定的结构化对象
Spring 通过特定的 PropertySource 优先级加载配置,并允许优先级高的配置覆盖优先级低的配置。
配置加载优先级
以下是 Spring 加载配置资源的优先级(从低到高):
- Spring Boot 的默认属性,通过
SpringApplication类中的setDefaultProperties方法执行。 @Configuration类上的@PropertySource指定的配置来源。- 属性配置文件。这个是最常用的配置来源,不同的配置文件也是存在优先级关系的。(见下文)
- 属性
random.*中的RandomValuePropertySource。比如random.int可以随机取一个 int 类型的随机值。 - 操作系统的环境变量。
- Java 系统属性
System.getProperties(),就是在java -D命令中指定的一些属性。 java:comp/env中的 JNDI 属性ServletContext初始化参数ServletConfig初始化参数SPRING_APPLICATION_JSON(环境变量和系统参数中的内联 JSON)中的属性,在 Spring 启动的时候会被解析并添加到Environment中。具体的配置方式有以下几种:- 将
SPRING_APPLICATION_JSON作为一个环境变量。 - 将
spring.application.json作为系统属性,如java -Dspring.application.json='{"name": "Tom"}' -jar app.jar。 - 将
spring.application.json作为命令行参数,如java -jar app.jar --spring.application.json='{"name": "Tom"}'。
- 将
- 命令行参数,也是比较常用的配置来源之一,比如
--server.port=8888,Spring 会把指定的配置添加到Environment中,如果不希望将命令行属性添加进去,可以通过SpringApplication.setAddCommandLineProperties(false)禁用它们。 - 测试类的
@SpringBootTest注解中的properties属性。 - 测试类的
@TestPropertySource执行的配置来源。 - DevTools 的全局设置属性,当 DevTools 启用的时候会生效,在
$HOME/.config/spring-boot目录下。
属性配置文件
在以上的第三点,提到了属性配置文件,这是开发者最常用的配置来源,每个 Spring Boot 应用中都会有大量的配置项在属性配置文件当中。属性配置文件之间也是有区分的,它们同样存在优先级数据,当同样的属性名配置了不同属性值的时候,优先级高的会覆盖优先级低的,以下顺序从低到高:
- 打包进 jar 的
application.properties或application.yaml文件。 - 打包进 jar 的
application-{profile}.properties或application-{profile}.yaml文件。 - jar 之外的
application.properties或application.yaml文件。 - jar 之外的
application-{profile}.properties或application-{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: 的意思是,指定的位置不一定存在这个文件。后面的配置文件路径,如果需要配置多个路径,使用 , 隔开即可。