Spring Boot 2.7.7:ConfigurationProperties映射Map<String, Integer>失败求助
Spring Boot 2.7.7配置映射Map<String, Integer>为空的问题排查
问题根源
配置路径不匹配
你的@ConfigurationProperties前缀设为limiter.settings,但类里的字段名又是settings,这会让Spring尝试绑定limiter.settings.settings路径下的配置,而你的yml配置是直接挂在limiter.settings节点下的a、b,根本不存在settings子节点,自然映射不到内容,得到空Map。final字段与构造方法的冲突
字段用了final修饰,还只加了@AllArgsConstructor,没有提供无参构造。Spring Boot默认的配置绑定逻辑需要无参构造实例化对象,再通过Setter注入属性,但final字段的Setter是无效的(无法修改final变量);如果想用构造绑定,还缺少@ConstructorBinding注解配合,导致无法正确注入Map。注解混用导致逻辑混乱
同时使用@Component和@EnableConfigurationProperties,前者会把类当作普通Bean注册,后者是专门处理配置属性Bean的机制,两者混用可能让Spring的Bean处理逻辑冲突,影响配置绑定效果。
解决办法
方案一:调整前缀+使用Setter注入(简单直观)
修改配置类,让路径匹配,去掉final字段和全参构造:
@Component @ConfigurationProperties(prefix = "limiter") @Getter @Setter public class LimiterSettings { private Map<String, Integer> settings; }
- 前缀改为
limiter,这样settings字段就对应yml里的limiter.settings节点,直接映射下面的a、b键值对。 - 去掉
final和@AllArgsConstructor,Lombok的@Getter@Setter会自动生成无参构造,Spring可以通过Setter完成属性注入。
方案二:构造绑定(适合不可变对象场景)
如果需要保留final字段,用构造绑定方式:
@ConfigurationProperties(prefix = "limiter") @ConstructorBinding @Getter public class LimiterSettings { private final Map<String, Integer> settings; public LimiterSettings(Map<String, Integer> settings) { this.settings = settings; } }
- 加上
@ConstructorBinding告诉Spring用构造方法注入配置属性。 - 移除类上的
@Component,在启动类或者任意配置类上添加@EnableConfigurationProperties(LimiterSettings.class),由该注解负责注册配置属性Bean。
使用验证
两种方案下,直接在LimiterService中注入即可:
public class LimiterService implements ILimiterService { private final LimiterSettings limiterSettings; @Autowired public LimiterService(LimiterSettings limiterSettings) { this.limiterSettings = limiterSettings; } }
内容的提问来源于stack exchange,提问作者littleAlien
相关产品推荐
相关产品推荐

