application.yaml加载原理

252 阅读3分钟

Spring Boot 中 application.yaml 的加载原理涉及环境初始化、配置文件定位、解析及属性绑定等多个步骤。


1. 加载流程概览

Spring Boot 通过 Environment 抽象 管理配置,application.yaml 的加载过程分为以下阶段:

  1. 触发时机:应用启动时,在 ApplicationEnvironmentPreparedEvent 事件 阶段加载配置文件。
  2. 文件定位:按预设路径搜索 application.yaml,优先级由高到低。
  3. 解析与合并:将 YAML 内容解析为键值对,合并到 EnvironmentPropertySource 链。
  4. 属性绑定:通过 @Value@ConfigurationProperties 将配置注入 Bean。

2. 核心组件

(1) ConfigFileApplicationListener

  • 作用:监听 ApplicationEnvironmentPreparedEvent 事件,负责加载 application.yamlapplication.properties

  • 流程

    1. 根据 spring.config.location 和默认路径搜索配置文件。
    2. 解析文件内容,生成 PropertySource 对象。
    3. PropertySource 添加到 Environment 中。

(2) YamlPropertySourceLoader

  • 作用:解析 YAML 文件,转换为 MapPropertySourceOriginTrackedMapPropertySource
  • 依赖库:使用 SnakeYAML 库解析 YAML 格式。

(3) Environment 接口

  • 实现类StandardServletEnvironmentStandardEnvironment
  • 存储结构:维护一个 MutablePropertySources 对象,包含多个 PropertySource(如系统属性、环境变量、配置文件等)。

3. 配置文件定位规则

(1) 默认搜索路径(优先级由高到低)

  1. 当前目录的 /config 子目录file:./config/
  2. 当前目录file:./
  3. classpath 的 /configclasspath:/config/
  4. classpath 根目录classpath:/

(2) 文件命名规则

  • 主文件application.yamlapplication.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 链按以下顺序添加(优先级由高到低):

  1. 命令行参数(--key=value)。
  2. 系统属性(System.getProperties())。
  3. 操作系统环境变量。
  4. application.yaml 配置文件(按路径优先级)。
  5. @Configuration 类上的 @PropertySource 注解。
  6. 默认属性(通过 SpringApplication.setDefaultProperties 设置)。

5. 配置解析与存储

(1) YAML 解析示例

# application.yaml
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb

解析后转换为 PropertySource 的键值对:

  • server.port=8080
  • spring.datasource.url=jdbc:mysql://localhost:3306/mydb

(2) 多文档块处理

YAML 支持多文档块(--- 分隔),按顺序合并:

# application.yaml
server:
  port: 8080
---
spring:
  profiles: dev
server:
  port: 8081
  • 默认激活时,server.port=8080
  • 激活 dev Profile 时,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 ServerJasypt 对敏感配置加密。

(3) 动态配置更新

  • Spring Cloud Config:结合 @RefreshScope 实现配置热更新。

总结

Spring Boot 通过以下步骤加载 application.yaml

  1. 事件触发:在环境准备阶段由 ConfigFileApplicationListener 处理。
  2. 路径搜索:按优先级定位文件。
  3. 解析与合并:将 YAML 转换为 PropertySource 并加入 Environment
  4. 属性绑定:通过注解将配置注入 Bean。 理解这一流程有助于灵活管理多环境配置、调试属性冲突及扩展自定义配置源。