@Value适合简单零散配置,@ConfigurationProperties适合结构化成组配置;前者支持SpEL和默认值但无校验,后者支持类型安全、JSR-303校验与松散绑定。

在 Spring 中读取外部配置,@Value 和 @ConfigurationProperties 是两种最常用的方式,它们适用场景不同:前者适合简单、零散的配置项,后者更适合结构化、成组的配置。用错容易导致类型转换失败、校验缺失或配置未生效等问题。
用 @Value 读取单个配置项
@Value 直接注入配置值,支持 SpEL 表达式,默认值用 #{...} 或 ${...:default} 语法。它不依赖配置类,但无法做批量绑定和校验。
- 基础写法:
@Value("${server.port:8080}") private int port;—— 支持默认值,类型自动转换(如 String → int) - 注意必须在 Spring 管理的 Bean 中使用(如
@Component、@Service),普通 new 出来的对象无效 - 复杂类型(如 List、Map)需配合 SpEL:
@Value("#{${app.urls:#{null}}}") private List<string> urls;</string>,但可读性和维护性差,不推荐用于多字段场景 - 如果配置不存在且没设默认值,启动会抛
IllegalArgumentException(除非加@Value("${xxx:}")空默认)
用 @ConfigurationProperties 绑定配置对象
@ConfigurationProperties 把配置前缀下的所有属性批量映射到一个 Java Bean,支持类型安全、JSR-303 校验、IDE 提示和松散绑定(如 my-app.name 自动匹配 myAppName)。
- 定义配置类,加上
@ConfigurationProperties(prefix = "app")和@Component(或通过@EnableConfigurationProperties注册) - 对应配置文件中写:
app.name=myapp、app.timeout=3000、app.features[0]=login、app.features[1]=pay - 字段建议用
private+getter/setter,Spring 需要 setter 才能注入;Lombok 的@Data可简化 - 加
@Validated并在字段上用@NotBlank、@Min(1)等注解,启动时自动校验
关键区别和选型建议
不是“哪个更好”,而是“什么情况该用哪个”:
立即学习“Java免费学习笔记(深入)”;
- 只读一两个配置?比如开关标志、超时毫秒数 —— 用
@Value更轻量 - 配置项超过 3 个,或有嵌套结构(如数据库连接池、第三方服务地址+密钥+重试策略)—— 一定用
@ConfigurationProperties - 需要配置刷新(
@RefreshScope)?两者都支持,但@ConfigurationProperties类天然更适合动态更新 - 配置来自不同来源(如 Consul、Nacos)?
@ConfigurationProperties仍适用,底层由 Spring Environment 统一加载
常见坑与修复
配置不生效?值为 null?启动报错?多数问题出在细节:
- 忘了加
@EnableConfigurationProperties或@Component—— 配置类不会被扫描,字段全为 null - 配置 key 写错(如
app.name写成app.nam),@ConfigurationProperties默认静默失败(可通过spring.devtools.restart.enabled=true+ 日志排查) -
@Value在 static 字段上无效 —— Spring 不支持注入 static 成员,改用非 static + setter 或构造器注入 - 配置文件编码不是 UTF-8(尤其 Windows 下的 application.properties),中文乱码 —— 显式指定
file.encoding=UTF-8启动参数


















