一句话总结
Spring Boot 配置优先级从高到低:命令行参数 > 系统环境变量 > application-{profile}.yml(外部)> application-{profile}.yml(内部)> application.yml(外部)> application.yml(内部)。核心原则:越外部的配置优先级越高、越具体的配置优先级越高。外部配置(jar 包外)覆盖内部配置(jar 包内),profile 特定配置覆盖通用配置。
初级理解
配置优先级(从高到低)
# Spring Boot 配置优先级(数字越小优先级越高)
# 1. 命令行参数(--server.port=8080)
# 2. SPRING_APPLICATION_JSON(环境变量中的 JSON)
# 3. JNDI 属性(java:comp/env)
# 4. System.getProperties()
# 5. 操作系统环境变量
# 6. RandomValuePropertySource(random.*)
# 7. jar 包外部的 application-{profile}.yml
# 8. jar 包内部的 application-{profile}.yml
# 9. jar 包外部的 application.yml
# 10. jar 包内部的 application.yml
# 11. @PropertySource 注解
# 12. SpringApplication.setDefaultProperties()
# 核心记忆
# 命令行 > 环境变量 > 外部 profile > 内部 profile > 外部默认 > 内部默认
多环境配置
# application.yml(公共配置)
server:
port: 8080
# application-dev.yml(开发环境)
server:
port: 8081
# application-prod.yml(生产环境)
server:
port: 80
# 激活环境
spring:
profiles:
active: dev # 使用 application-dev.yml
# 最终 server.port = 8081(dev 覆盖了公共配置)
中级深入
外部配置 vs 内部配置
# 外部配置(jar 包外,优先级高)
# 1. jar 包同级目录的 config/ 子目录
# ./config/application.yml
# 2. jar 包同级目录
# ./application.yml
# 3. classpath 中的 config/ 包
# classpath:/config/application.yml
# 4. classpath 根目录
# classpath:/application.yml
# 优先级:1 > 2 > 3 > 4
# 外部 config/ > 外部根目录 > 内部 config/ > 内部根目录
# 运维场景:jar 包外放 application.yml
# java -jar app.jar --spring.config.location=/etc/app/application.yml
命令行参数覆盖
# 命令行参数优先级最高
java -jar app.jar --server.port=9090 --app.name=test
# 即使 application.yml 中配置了 server.port=8080
# 最终生效的是 9090
# 禁用命令行参数
SpringApplication app = new SpringApplication(App.class);
app.setAddCommandLineProperties(false);
app.run(args);
高级拓展
配置中心优先级
# Nacos 配置中心 + Spring Boot 配置优先级
# 1. Nacos 配置中心(shared-configs,共享配置)
# 2. Nacos 配置中心(extension-configs,扩展配置)
# 3. Nacos 配置中心(应用专属配置)
# 4. bootstrap.yml
# 5. application.yml
# bootstrap.yml vs application.yml
# bootstrap.yml:父上下文,最早加载,用于配置中心连接信息
# application.yml:子上下文,业务配置
# bootstrap.yml 示例
spring:
application:
name: user-service
cloud:
nacos:
config:
server-addr: localhost:8848
file-extension: yml
# 配置中心配置覆盖本地配置
# Nacos 中的 user-service.yml 会覆盖本地的 application.yml
动态刷新配置
# @RefreshScope 实现配置热更新
@RestController
@RefreshScope // 配置变更时重新创建 Bean
public class ConfigController {
@Value("${app.message:Hello}")
private String message;
@GetMapping("/message")
public String getMessage() {
return message; // Nacos 修改配置后自动更新
}
}
# 原理
# 1. Nacos 配置变更 → 发送 RefreshEvent
# 2. @RefreshScope 的 Bean 被标记为 dirty
# 3. 下次访问时重新创建 Bean,获取新配置
实战场景
场景:Docker 环境配置
# Docker 部署时通过环境变量覆盖配置
# docker-compose.yml
services:
app:
image: my-app:latest
environment:
- SERVER_PORT=8080
- SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/mydb
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=secret
ports:
- "8080:8080"
# 环境变量映射规则
# server.port → SERVER_PORT
# spring.datasource.url → SPRING_DATASOURCE_URL
# 点号 → 下划线,全大写
面试模拟
面试官:Spring Boot 配置加载优先级是怎样的?
你:命令行参数最高,其次是环境变量,然后是外部配置文件(jar 包外),最后是内部配置文件(jar 包内)。profile 特定配置覆盖通用配置。核心原则:越外部优先级越高,越具体优先级越高。
面试官:bootstrap.yml 和 application.yml 有什么区别?
你:bootstrap.yml 由父 ApplicationContext 加载,优先级更高,最早加载,通常用于配置中心连接信息(如 Nacos 地址)。application.yml 由子 ApplicationContext 加载,用于业务配置。Spring Cloud 配置中心的配置会覆盖 application.yml。