@Value 与外部化配置 PropertySource

引言

把 URL、开关、页面大小等参数写死在代码里,改一次就要重新编译。Spring 用 Environment + PropertySource 抽象把配置外部化:属性来自系统环境、JVM 参数或属性文件,Bean 用 @Value("${...}") 读取。本章讲属性来源的注册与读取。

核心概念

  • Environment(ConfigurableEnvironment):按优先级管理一组 PropertySource(属性来源)。context.getEnvironment().getProperty("key") 可取任意来源的值。
  • @PropertySource(6.x 为 org.springframework.context.annotation):把一个 .properties 文件注册成 PropertySource,通常标在 @Configuration 类上。
  • @Value:字段/参数上 @Value("${key}") 取属性,@Value("${key:default}") 带默认值;#{...} 则走 SpEL(第 18 章)。
  • 占位符解析器:${...}PropertySourcesPlaceholderConfigurer(实现 BeanFactoryPostProcessor)负责解析,需要显式注册为一个静态 @Bean(Boot 应用会自动注册)。
  • 优先级示例(由高到低,以官方文档为准):命令行/JVM 参数 → 系统环境变量 → 外部配置文件 → classpath 配置文件,后注册的 PropertySource 排前面。

代码示例

// 配置文件 app.properties
// report.page-size=20
// report.title=日报

@Configuration
@PropertySource("classpath:app.properties")
public class AppConfig {
    // PropertySourcesPlaceholderConfigurer 是 BeanFactoryPostProcessor,
    // @Configuration 里必须用 static 方法提前实例化,${...} 才能解析
    @Bean
    public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

@Component
public class ReportProperties {
    @Value("${report.page-size:10}")   // 缺省兜底 10
    private int pageSize;

    @Value("${report.title}")          // 缺失且无默认值 → 启动报错
    private String title;

    // 也可以直接注入 Environment 编程读取
    private final org.springframework.core.env.Environment env;
    public ReportProperties(Environment env) { this.env = env; }

    public String resolve(String key) { return env.getProperty(key); }
}

注意点

  • 纯 Spring(非 Boot)注解环境下,忘了注册 PropertySourcesPlaceholderConfigurer@Value 不会报错,而是注入字面量 ${report.title}——这是经典坑。
  • 值缺失又没写默认值,容器启动会因无法解析占位符直接失败,比运行期才发现好。
  • @PropertySource 默认用系统默认编码读文件,中文属性建议用 UTF-8 文件并在 Spring Boot 外自行留意(官方推荐 properties 用 ASCII/Unicode 转义或改 UTF-8 支持)。
  • @Value 注入的是“字符串转换后的类型”,int/boolean 等基础类型 Spring 自动转换;复杂类型转换需 ConversionService
  • 同 key 多来源时按 PropertySource 顺序取第一个命中值,别靠猜,用 env.getPropertySources() 排查。

小结

外部化配置 = Environment 统一管理 PropertySource + @PropertySource 挂载文件 + @Value("${key:default}") 读取。记得注册占位符解析器;Spring Boot 在 application.properties 上把这套机制做成了默认行为,理解本章即可无痛迁移。

笔记加载中…