全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-18 8 分钟 ✍️ juanwangdev

环境准备与属性源加载

环境准备是 Spring Boot 启动的关键阶段,负责加载和合并所有配置源。

启动入口分析

SpringApplication.run()

Java
public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();

    // 1. 创建引导上下文
    DefaultBootstrapContext bootstrapContext = createBootstrapContext();

    // 2. 准备环境 ← 本节重点
    ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, args);

    // 3. 创建应用上下文
    context = createApplicationContext();

    // ...
}

prepareEnvironment() 核心流程

Java
private ConfigurableEnvironment prepareEnvironment(
        SpringApplicationRunListeners listeners,
        DefaultBootstrapContext bootstrapContext,
        ApplicationArguments applicationArguments) {
    // 1. 创建环境对象
    ConfigurableEnvironment environment = getOrCreateEnvironment();

    // 2. 配置环境
    configureEnvironment(environment, applicationArguments.getSourceArgs());

    // 3. 附加默认属性源
    ConfigurationPropertySources.attach(environment);

    // 4. 发布环境准备事件
    listeners.environmentPrepared(bootstrapContext, environment);

    return environment;
}

Environment 创建

环境类型选择

Java
protected ConfigurableEnvironment createEnvironment() {
    return new ApplicationEnvironment(); // Servlet 环境
    // Reactive 环境使用 ApplicationReactiveEnvironment
    // 非 Web 环境使用 StandardEnvironment
}

环境继承体系

Java
ApplicationEnvironment
    ↓ extends
StandardServletEnvironment
    ↓ extends
StandardEnvironment
    ↓ implements
ConfigurableEnvironment

属性源加载顺序

加载优先级(从高到低)

Java
1. 命令行参数 (CommandLineArguments)
2. JVM 系统属性 (SystemProperties)
3. 操作系统环境变量 (SystemEnvironment)
4. application-{profile}.yml/properties
5. application.yml/properties
6. @ConfigurationProperties 默认值
7. @PropertySource 注解
8. 默认属性 (SpringApplication.setDefaultProperties)

属性源加载源码

YAML
protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {
    MutablePropertySources propertySources = environment.getPropertySources();

    // 1. 添加默认属性
    if (this.defaultProperties != null) {
        propertySources.addLast(
            new MapPropertySource("defaultProperties", this.defaultProperties));
    }

    // 2. 添加命令行参数(最高优先级)
    if (args.length > 0) {
        propertySources.addFirst(
            new SimpleCommandLinePropertySource(args));
    }
}

ConfigFileApplicationListener

配置文件加载

Java
// Spring Boot 2.4+ 使用 ConfigDataEnvironmentPostProcessor
public class ConfigFileApplicationListener implements EnvironmentPostProcessor {
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        // 加载 application.yml/properties
        load(application, environment);
    }

    protected void load(ConfigurableEnvironment environment) {
        // 按顺序加载:
        // 1. file:./config/
        // 2. file:./
        // 3. classpath:/config/
        // 4. classpath:/
    }
}

配置文件搜索路径

YAML
# 搜索顺序(后加载覆盖先加载)
file:./config/application.yml     # 优先级最高
file:./application.yml
classpath:/config/application.yml
classpath:/application.yml        # 优先级最低

Profile 激活机制

Profile 加载

Java
protected void onEnvironmentPrepared(ConfigurableEnvironment environment) {
    // 1. 获取激活的 Profile
    Set<String> activeProfiles = environment.getActiveProfiles();

    // 2. 加载 Profile 配置文件
    // application-{profile}.yml
}

Profile 配置方式

Java
# application.yml
spring:
  profiles:
    active: dev

---
# application-dev.yml
spring:
  config:
    activate:
      on-profile: dev

自定义属性源

实现 PropertySource

properties
public class CustomPropertySource extends PropertySource<Object> {
    public CustomPropertySource(String name) {
        super(name);
    }

    @Override
    public Object getProperty(String name) {
        // 自定义属性获取逻辑
        if ("custom.property".equals(name)) {
            return "custom-value";
        }
        return null;
    }
}

注册属性源

Java
@Configuration
public class CustomPropertySourceConfig implements EnvironmentPostProcessor {
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        environment.getPropertySources().addFirst(
            new CustomPropertySource("customSource"));
    }
}

注册到 spring.factories

text
org.springframework.boot.env.EnvironmentPostProcessor=\
com.example.CustomPropertySourceConfig

属性绑定机制

Binder 使用

text
@ConfigurationProperties(prefix = "app")
public class AppProperties {
    private String name;
    private int port;
    // getters/setters
}

// 绑定方式
@Configuration
public class BindingConfig {
    @Bean
    public AppProperties appProperties(ConfigurableEnvironment environment) {
        return Binder.get(environment)
            .bind("app", AppProperties.class)
            .orElse(new AppProperties());
    }
}

注意:命令行参数优先级最高,可用于覆盖配置文件中的值。

要点总结

  • 环境准备在 ApplicationContext 创建之前完成
  • 属性源按优先级加载,命令行参数优先级最高
  • 配置文件按 file → classpath 顺序搜索
  • Profile 实现多环境配置切换
  • 可通过 EnvironmentPostProcessor 扩展属性源

📝 发现内容有误?点击此处直接编辑

← 上一篇 内嵌 Web 容器启动
下一篇 → 监听器与事件机制
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库