Spring中@ConfigurationProperties与@Value配合使用的赋值异常问题
当你在record上标注@ConfigurationProperties时,Spring是通过配置属性绑定机制来初始化record的构造函数参数的,这个流程和@Value的属性注入逻辑完全独立。@ConfigurationProperties只会根据指定前缀+参数名称(或自定义属性名)匹配配置文件里的键,根本不会识别参数上的@Value注解,所以property2始终无法被赋值,结果就是null。
另外record是不可变类型,所有属性完全依赖构造函数初始化,而@Value的注入逻辑通常针对字段或普通Bean的方法参数,在@ConfigurationProperties管理的record场景下,Spring不会触发@Value的解析流程。
方案一:纯用@ConfigurationProperties绑定(推荐)
既然已经指定了前缀abc,直接利用配置属性绑定规则匹配配置项,完全不需要@Value:
方式1:调整record参数名(适配驼峰转下划线规则)
Spring Boot配置属性绑定默认支持驼峰转下划线的映射,把property2改成propertyName2,就能自动匹配配置里的property_name2:
@ConfigurationProperties(prefix = "abc") public record Model( String property1, String propertyName2) { }
方式2:用@ConfigurationProperties指定属性名
如果不想修改参数名,给参数单独加@ConfigurationProperties注解指定对应的配置键即可:
@ConfigurationProperties(prefix = "abc") public record Model( String property1, @ConfigurationProperties(name = "property_name2") String property2) { }
方案二:改用@Value注入(放弃@ConfigurationProperties前缀)
如果必须用@Value,需要把record作为普通Spring Bean来管理,不能依赖@ConfigurationProperties的前缀绑定。比如用@Component标注record,然后在构造函数参数上直接写@Value:
@Component public record Model( @Value("${abc.property1}") String property1, @Value("${abc.property_name2}") String property2) { }
这种方式需要手动写全配置键,没法利用@ConfigurationProperties的前缀简化配置。
用方案一的任意一种方式调整后,输出会变成:
Model[property1=value1, propertyName2=value2]
(或对应参数名的正确赋值结果)
内容的提问来源于stack exchange,提问作者Swanand

