Spring Boot 中 application.yaml 的加载原理涉及环境初始化、配置文件定位、解析及属性绑定等多个步骤。
1. 加载流程概览
Spring Boot 通过 Environment 抽象 管理配置,application.yaml 的加载过程分为以下阶段:
- 触发时机:应用启动时,在
ApplicationEnvironmentPreparedEvent事件 阶段加载配置文件。 - 文件定位:按预设路径搜索
application.yaml,优先级由高到低。 - 解析与合并:将 YAML 内容解析为键值对,合并到
Environment的PropertySource链。 - 属性绑定:通过
@Value或@ConfigurationProperties将配置注入 Bean。
2. 核心组件
(1) ConfigFileApplicationListener
-
作用:监听
ApplicationEnvironmentPreparedEvent事件,负责加载application.yaml和application.properties。 -
流程:
- 根据
spring.config.location和默认路径搜索配置文件。 - 解析文件内容,生成
PropertySource对象。 - 将
PropertySource添加到Environment中。
- 根据
(2) YamlPropertySourceLoader
- 作用:解析 YAML 文件,转换为
MapPropertySource或OriginTrackedMapPropertySource。 - 依赖库:使用 SnakeYAML 库解析 YAML 格式。
(3) Environment 接口
- 实现类:
StandardServletEnvironment或StandardEnvironment。 - 存储结构:维护一个
MutablePropertySources对象,包含多个PropertySource(如系统属性、环境变量、配置文件等)。
3. 配置文件定位规则
(1) 默认搜索路径(优先级由高到低)
- 当前目录的
/config子目录:file:./config/ - 当前目录:
file:./ - classpath 的
/config包:classpath:/config/ - classpath 根目录:
classpath:/
(2) 文件命名规则
- 主文件:
application.yaml或application.properties。 - Profile 特定文件:
application-{profile}.yaml(如application-dev.yaml)。
(3) 自定义路径
-
通过
spring.config.location指定外部路径(覆盖默认路径):java -jar app.jar --spring.config.location=classpath:/default/,file:./custom/ -
通过
spring.config.name修改主文件名:java -jar app.jar --spring.config.name=myconfig
4. 配置加载顺序与优先级
(1) 优先级规则
- 路径优先级:越具体的路径优先级越高(如
file:./config/>classpath:/)。 - Profile 激活顺序:后激活的 Profile 覆盖先激活的配置。
- 属性覆盖:同一文件中,后定义的属性覆盖先定义的属性。
(2) 属性源顺序
Environment 中的 PropertySource 链按以下顺序添加(优先级由高到低):
- 命令行参数(
--key=value)。 - 系统属性(
System.getProperties())。 - 操作系统环境变量。
application.yaml配置文件(按路径优先级)。@Configuration类上的@PropertySource注解。- 默认属性(通过
SpringApplication.setDefaultProperties设置)。
5. 配置解析与存储
(1) YAML 解析示例
# application.yaml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
解析后转换为 PropertySource 的键值对:
server.port=8080spring.datasource.url=jdbc:mysql://localhost:3306/mydb
(2) 多文档块处理
YAML 支持多文档块(--- 分隔),按顺序合并:
# application.yaml
server:
port: 8080
---
spring:
profiles: dev
server:
port: 8081
- 默认激活时,
server.port=8080。 - 激活
devProfile 时,server.port=8081。
6. 属性绑定到 Bean
(1) @Value 注解
@Component
public class MyBean {
@Value("${server.port}")
private int port;
}
(2) @ConfigurationProperties
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceConfig {
private String url;
// Getter & Setter
}
7. 调试与验证
(1) 查看所有 PropertySource
@SpringBootApplication
public class App {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(App.class, args);
Environment env = context.getEnvironment();
env.getPropertySources().forEach(ps -> System.out.println(ps.getName()));
}
}
输出示例:
configurationProperties
systemProperties
systemEnvironment
applicationConfig: [classpath:/application.yaml]
(2) 激活 Profile
java -jar app.jar --spring.profiles.active=dev
8. 高级特性
(1) 多环境配置
- 文件命名:
application-{profile}.yaml。 - 激活方式:命令行参数、环境变量、
spring.profiles.active配置。
(2) 加密配置
- 使用 Spring Cloud Config Server 或 Jasypt 对敏感配置加密。
(3) 动态配置更新
- Spring Cloud Config:结合
@RefreshScope实现配置热更新。
总结
Spring Boot 通过以下步骤加载 application.yaml:
- 事件触发:在环境准备阶段由
ConfigFileApplicationListener处理。 - 路径搜索:按优先级定位文件。
- 解析与合并:将 YAML 转换为
PropertySource并加入Environment。 - 属性绑定:通过注解将配置注入 Bean。 理解这一流程有助于灵活管理多环境配置、调试属性冲突及扩展自定义配置源。