外部化配置与优先级
本教程共 48 篇 · 第 12 篇 · 更新于 2026-08-13 · 约 5 分钟阅读
本节目标:搞懂 Spring Boot 十几类配置来源的优先级顺序,学会用命令行、环境变量、外部文件覆盖配置。
什么是外部化配置
同一份代码,要跑在开发、测试、生产三个环境。
每个环境的数据库地址、端口都不一样。代码不能改,配置必须能变。
Spring Boot 的办法:配置全部「外部化」。启动时从十几个来源收集属性,按固定顺序合并。
顺序靠后来源的优先级更高,可以覆盖前面的值。
官方优先级顺序
以 Spring Boot 4.1.0 官方文档为准,完整顺序如下(从低到高):
- 默认属性:
SpringApplication.setDefaultProperties(...)设置的 Map。 @PropertySource注解引入的属性文件。- 配置文件:jar 内的
application.properties/application.yml。 - 随机值属性源:
random.*。 - OS 环境变量。
- Java 系统属性:
System.getProperties()。 - JNDI 属性:
java:comp/env。 ServletContext初始化参数。ServletConfig初始化参数。SPRING_APPLICATION_JSON:内嵌 JSON 的环境变量或系统属性。- 命令行参数。
测试场景还有 @TestPropertySource、@DynamicPropertySource 等来源,优先级更高。日常开发记住前 11 条就够。
Warning别背反了:列表越靠后,优先级越高。命令行参数是王者,能覆盖所有文件配置。
命令行参数
启动时用 -- 前缀传参,直接变属性:
java -jar hello-app.jar --server.port=9000 --spring.profiles.active=prod
开发时用 Maven 插件传:
mvn spring-boot:run -Dspring-boot.run.arguments="--server.port=9000"
Tip
-Dserver.port=9000是系统属性,不是命令行参数,优先级低一档。两者写法不同,别混淆。
不想要命令行参数进 Environment,可以关掉:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(Application.class);
application.setAddCommandLineProperties(false);
application.run(args);
}
}
SPRING_APPLICATION_JSON
把一整块配置编码成 JSON,塞进一个变量:
SPRING_APPLICATION_JSON='{"server":{"port":9000},"app":{"name":"hello"}}' java -jar hello-app.jar
Windows 用 set 设置同名变量再启动即可。也支持系统属性和命令行参数形式:
java -Dspring.application.json='{"server":{"port":9000}}' -jar hello-app.jar
适合容器平台注入复杂配置的场景。
环境变量与系统属性
环境变量名不能带点和横线,Spring Boot 有转换规则:
- 点换成下划线。
- 横线去掉。
- 全部转大写。
server.servlet.context-path 对应 SERVER_SERVLETCONTEXTPATH。
spring.main.log-startup-info 对应 SPRING_MAIN_LOGSTARTUPINFO。
Note官方示例
SPRING_MAIN_LOGSTARTUPINFO是去掉横线后的写法。很多教程写SPRING_MAIN_LOG_STARTUP_INFO也能绑上,因为下划线是分隔符;规则记「点变下划线、横线删除、全大写」最稳妥。
系统属性用法:
java -Dserver.port=9000 -jar hello-app.jar
配置文件的搜索位置
application.properties / application.yml 不止 classpath 一处。默认按顺序搜索:
- classpath 根目录。
- classpath 的
/config目录。 - 当前目录。
- 当前目录的
config/子目录。 config/的直属子目录(config/*/)。
后找到的覆盖先找到的。jar 外部的配置文件,天然能覆盖 jar 内部的默认值。
部署时把配置文件放在 jar 同目录的 config/ 下,是常见做法。
配置文件内部的加载顺序
光知道「配置文件」排第三优先级还不够。
配置文件自己还有一层顺序,从低到高:
- jar 内的
application.properties/application.yml(普通文件)。 - jar 外的
application.properties/application.yml(普通文件)。 - jar 内的
application-{profile}变体。 - jar 外的
application-{profile}变体。
结论:同位置下,profile 文件覆盖普通文件;jar 外覆盖 jar 内。
部署时把生产配置放到 jar 外,代码仓库里只留默认值,是最干净的分工。
spring.config.import 导入外部文件
2.4 起支持用 spring.config.import 引入额外配置。
在 application.yml 里声明:
spring:
config:
import: optional:file:./dev.properties
启动时会去当前目录找 dev.properties,找不到也不报错。
导入文件里的值,优先级高于触发导入的文件。
多个位置用逗号分隔,后面的覆盖前面的:
spring:
config:
import:
- optional:file:./base.properties
- optional:file:./override.properties
Note
optional:前缀很重要。不加的话,文件不存在会让应用启动失败。
自定义文件名与位置
不想用 application 这个名字?用 spring.config.name:
java -jar hello-app.jar --spring.config.name=myapp
指定外部配置文件位置:
java -jar hello-app.jar --spring.config.location=file:/etc/hello/config/
spring.config.location 会替换默认搜索位置。想保留默认位置、只追加,用 additional-location:
java -jar hello-app.jar --spring.config.additional-location=file:/etc/hello/override.properties
位置不存在会启动失败。加 optional: 前缀容忍缺失:
java -jar hello-app.jar --spring.config.additional-location=optional:file:/etc/hello/override.properties
Tip这几个键在启动极早期就要用,只能通过命令行参数、环境变量或系统属性传入,写进配置文件里不生效。
环境变量直接引用
配置文件里用 ${...} 引用环境变量,是容器部署的标配:
spring:
datasource:
url: ${DATABASE_URL}
username: ${DB_USER:root}
:root 是默认值。环境变量没设置时用 root。
一个完整的覆盖例子
假设 jar 内配置:
server.port=8080
app.name=hello
部署命令:
export APP_NAME=hello-prod
java -jar hello-app.jar --server.port=9000
最终生效:端口 9000(命令行赢),应用名 hello-prod(环境变量赢)。
测试场景的属性来源
测试里还有几类更高优先级的来源:
@TestPropertySource指定的属性文件。@DynamicPropertySource动态注册的属性。@SpringBootTest的properties属性。
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(properties = {"server.port=0", "app.message=test"})
class ApplicationTests {
}
测试属性压过命令行参数,保证测试环境不被外部变量干扰。
配置排错
值不符合预期时,按优先级从高到低排查。Actuator 的 env 端点能看每个属性的最终值和来源:
curl http://localhost:8080/actuator/env
没启用 Actuator 的话,启动加 --debug 也能看到配置相关调试信息(条件报告详见 §6)。
小结
- 外部化配置让同一份代码适配多环境。
- 优先级从低到高:默认属性 → @PropertySource → 配置文件 → 环境变量 → 系统属性 → JNDI → Servlet 参数 → SPRING_APPLICATION_JSON → 命令行参数。
- 环境变量名规则:点变下划线、去横线、全大写。
- 外部配置文件用
spring.config.location/additional-location指定。 - 命令行参数是王者,能覆盖所有文件配置。
- 同位置下 profile 文件覆盖普通文件,jar 外覆盖 jar 内。
spring.config.import可以引入外部文件,记得加optional:。- 测试属性优先级最高,隔离测试环境。
- 排错用
/actuator/env或--debug。