★ @ConfigurationProperties 如何绑定配置?宽松绑定规则有哪些?与 @Value 有何区别?
结论先行:@ConfigurationProperties 用“前缀 + 类型安全”的方式把外部配置批量绑定到 POJO,天然支持宽松绑定(kebab-case、驼峰、大写环境变量自由对应),适合一组相关配置;@Value 做单个值注入、不支持宽松绑定,适合读取散值。推荐:多字段配置用 @ConfigurationProperties,零散单值用 @Value。
一、基本用法
# application.yml
app:
datasource:
url: jdbc:mysql://localhost:3306/demo
pool-size: 10
@ConfigurationProperties(prefix = "app.datasource") // 绑定前缀
public class DataSourceProps {
private String url; // 需 getter/setter 或 record
private int poolSize; // 属性名宽松匹配 pool-size
// getter/setter 省略
}
启用方式三选一:类上再加 @Component;启动类加 @EnableConfigurationProperties(DataSourceProps.class);包上加 @ConfigurationPropertiesScan。
二、宽松绑定(Relaxed Binding)规则
| 写法位置 | 示例 | 说明 |
|---|---|---|
| yml/properties | app.datasource.pool-size | 推荐 kebab-case(规范写法) |
| Java 属性名 | poolSize | 自动映射 pool-size |
| 环境变量 | APP_DATASOURCE_POOLSIZE | 大写 + 下划线,替换 . 与 - |
| 命令行 | --app.datasource.pool-size=10 | 系统属性同 yml 规则 |
因此同一份属性类可同时被配置文件、环境变量、命令行三种方式覆盖,无需改代码。
三、与 @Value 对比
| 维度 | @ConfigurationProperties | @Value |
|---|---|---|
| 绑定方式 | 类型安全批量绑定 | 单个占位符注入 |
| 宽松绑定 | 支持 | 不支持(需精确键名) |
| 校验 | 支持 @Validated + JSR-303 | 需要手工校验 |
| 复杂类型 | List/Map/嵌套对象均可 | 较弱 |
| 元数据提示 | 支持 | 不支持 |
| 适用 | 成组配置 | 零散配置、SpEL 计算值 |
四、进阶要点
- 校验:类上加 @Validated,字段上用 jakarta.validation 注解(如 @NotBlank、@Max);
- 不可变对象:构造器绑定——类上 @ConfigurationProperties + @ConstructorBinding(Boot 3 中 record 默认构造器绑定),省去 setter;
- 覆盖顺序:与普通配置一致,外部环境变量/命令行 > profile 文件 > 默认 yml;
- 第三方组件属性类(如 server.、spring.data.redis.)内部都走同一机制,所以能通过 yml/环境变量自由覆盖。
常见追问 / 记忆点
- 追问:yml 里是 pool-size,Java 里是 poolSize,能绑上吗?答:能,宽松绑定自动转换连字符与驼峰。
- 追问:为什么 @Value 拿不到大写环境变量?答:@Value 不做宽松归一化,需精确写键名(通常建议改用 @ConfigurationProperties)。
- 记忆点:前缀一批、类型安全、宽松绑定;成组用 Properties、散值用 @Value。