Skip to content

SpringBoot配置文件读取的各种方式

方式适用场景优点缺点
@Value单个、少量配置注入简单直观松散绑定差,不支持复杂对象
@ConfigurationProperties结构化、批量配置类型安全、支持校验、IDE提示需额外注解/类定义
Environment运行时动态获取灵活、可编程无编译期检查,代码冗余
@PropertySource加载自定义非标准文件扩展性强仅支持 Properties (YAML需特殊处理)

⚠️ Spring Boot 3 重要变更

  • 必须使用 JDK 17+
  • @ConfigurationProperties 完美支持 Java Record 类(不可变配置)
  • 推荐使用 @ConfigurationPropertiesScan@EnableConfigurationProperties 替代旧的 @Component 扫描方式

准备工作

添加依赖(可选但推荐)

为了获得 IDE 自动补全和元数据提示,建议添加:

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

示例配置文件 application.yml

yaml
app:
  name: MyAwesomeApp
  version: 3.0.0
  features:
    enable-cache: true
    max-retry: 3
  mail:
    host: smtp.example.com
    port: 587
    credentials:
      username: admin
      password: secret

四种读取方式详解

方式一:@Value —— 简单注入

适合注入单个值,支持 SpEL 表达式和默认值。

java
@RestController
public class SimpleController {

    // 基本注入
    @Value("${app.name}")
    private String appName;

    // 带默认值(冒号后为默认值)
    @Value("${app.description:No description provided}")
    private String description;

    // SpEL 表达式
    @Value("#{${app.features.max-retry} * 2}")
    private int doubleRetry;
}

💡 注意@Value 不支持直接映射 Map/List 等复杂结构,也不支持从 YAML 的层级结构中自动绑定嵌套对象。

方式二:@ConfigurationProperties —— ⭐ 最佳实践

✅ 推荐:使用 Record(Spring Boot 3 新特性)

java
// 不可变、线程安全、简洁
@ConfigurationProperties(prefix = "app")
public record AppProperties(
        String name,
        String version,
        Features features,
        Mail mail
) {
    // 嵌套配置也用 Record
    public record Features(boolean enableCache, int maxRetry) {}
    
    public record Mail(String host, int port, Credentials credentials) {}
    
    public record Credentials(String username, String password) {}
}

传统 POJO 写法(仍然有效)

java
@ConfigurationProperties(prefix = "app")
@Data  // Lombok
public class AppProperties {
    private String name;
    private String version;
    private Features features;
    
    @Data
    public static class Features {
        private boolean enableCache;
        private int maxRetry;
    }
}

注册配置类的三种方式

java
// 方式A:在启动类或配置类上启用(推荐)
@EnableConfigurationProperties(AppProperties.class)
@SpringBootApplication
public class Application { }

// 方式B:全局扫描(适合多个配置类)
@ConfigurationPropertiesScan("com.example.config")
@SpringBootApplication
public class Application { }

// 方式C:直接在配置类上加 @Component(旧方式,仍可用但不推荐)
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties { }

添加参数校验

java
@ConfigurationProperties(prefix = "app")
@Validated  // ← 开启校验
public record AppProperties(
        @NotBlank String name,
        @Min(1) @Max(10) int maxRetry,
        @Email String adminEmail
) {}

需引入 spring-boot-starter-validation 依赖。

方式三:Environment —— 编程式读取

适合在框架代码、条件逻辑中动态获取配置。

java
@Service
public class DynamicConfigService {

    private final Environment env;

    public DynamicConfigService(Environment env) {
        this.env = env;
    }

    public String getDbUrl() {
        // 返回 Optional 风格的安全获取
        return env.getProperty("spring.datasource.url", "jdbc:h2:mem:default");
    }

    public boolean isProfileActive(String profile) {
        return env.acceptsProfiles(Profile.of(profile));
    }
}

方式四:@PropertySource —— 加载自定义文件

java
@Configuration
@PropertySource("classpath:custom-config.properties")
// ⚠️ YAML 文件不直接被 @PropertySource 支持!
// 如需加载自定义 YAML,需自定义 PropertySourceFactory
public class CustomConfig { }

自定义 YAML 工厂示例:

java
public class YamlPropertySourceFactory implements PropertySourceFactory {
    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) 
            throws IOException {
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        factory.setResources(resource.getResource());
        Properties properties = factory.getObject();
        return new PropertiesPropertySource(
            resource.getResource().getFilename(), properties
        );
    }
}

// 使用
@PropertySource(value = "classpath:custom.yml", factory = YamlPropertySourceFactory.class)

配置优先级(从高到低)

1. 命令行参数 (--app.name=xxx)
2. JNDI 属性
3. Java 系统属性 (System.getProperties())
4. OS 环境变量
5. application-{profile}.yml / .properties
6. application.yml / .properties
7. @PropertySource 导入的文件
8. 默认属性 (SpringApplication.setDefaultProperties)

🔑 记忆口诀外部 > 内部,命令行 > 文件,Profile > 通用

选型决策树

需要读取配置?
├── 只读 1~2 个简单值 → @Value
├── 结构化 / 一组相关配置 → @ConfigurationProperties
│   ├── 不可变 / JDK17+ → Record ⭐
│   └── 需要可变 / 兼容旧代码 → POJO
├── 运行时动态决定 key → Environment
└── 加载非标准外部文件 → spring.config.import / @PropertySource

📌 总结:在 Spring Boot 3 项目中,优先使用 @ConfigurationProperties + Record 作为配置读取的标准范式。它提供了类型安全、IDE 友好、校验支持和不可变性保障,是现代 Spring 应用配置管理的最佳实践。