SpringBoot中@ConfigurationProperties无法初始化Map类型属性,获取值始终为null
我来帮你排查下这个问题,你遇到Map里的属性始终为null的情况,主要是两个配置细节没处理对,咱们一步步来解决:
问题1:配置属性与类字段的映射不匹配
你的ServiceModelConfiguration类用了@ConfigurationProperties(prefix = "input"),但类里的Map字段名叫properties,这会让Spring Boot去寻找**input.properties.***开头的配置项,可你的application.properties里都是input.default.*、input.serviceA.*这种结构,完全不匹配,所以Spring Boot根本没法把配置绑定到这个Map上,自然就是null了。
要匹配你当前的配置结构,有两种调整方式:
方式A:修改类结构适配现有配置
让input前缀下的子节点(default、serviceA这些)直接作为Map的key,调整后的类如下:
@Component @ConfigurationProperties public class ServiceModelConfiguration { // input字段对应配置文件中的input节点,其下的default、serviceA作为Map的key private Map<String, ServiceModel> input; public Map<String, ServiceModel> getInput() { return input; } public void setInput(Map<String, ServiceModel> input) { this.input = input; } public ServiceModel getServiceProperty(String key) { // 先判空,避免空指针异常 if (input == null) { return null; } return input.get(key); } public static class ServiceModel { private String host; private String ip; private String desc; // 必须添加无参构造函数 public ServiceModel() {} public ServiceModel(String host, String ip, String desc) { this.host = host; this.ip = ip; this.desc = desc; } // 完整的getter和setter方法 public String getHost() { return host; } public void setHost(String host) { this.host = host; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } } }
方式B:修改配置文件适配现有类结构
给所有配置项加上中间层级,匹配类里的properties字段:
input.properties.default.host=Default input.properties.default.ip=127.0.0.1 input.properties.default.desc=Default Desc input.properties.serviceA.host=ServiceA input.properties.serviceA.ip=192.168.21.1 input.properties.serviceA.desc=ServiceA Desc input.properties.serviceB.host=ServiceB input.properties.serviceB.ip=192.168.21.22 input.properties.serviceB.desc=ServiceB Desc
问题2:ServiceModel缺少无参构造函数
你的ServiceModel只有带参数的构造函数,但Spring Boot的属性绑定机制需要通过无参构造函数实例化对象,再调用setter方法注入属性。没有无参构造函数的话,Spring Boot无法创建ServiceModel实例,绑定就会失败,导致Map里的对象都是null。
所以不管用哪种方式,都必须给ServiceModel添加无参构造函数,同时确保所有属性都有对应的setter方法。
验证修改
调整完之后,你的PrintServices类不需要修改,直接调用printAllServiceProperties()就能正确获取到属性值了。另外建议你在获取属性时增加null判断,避免空指针异常:
public void printAllServiceProperties() { ServiceModel serviceA = serviceModelConfiguration.getServiceProperty("serviceA"); if (serviceA != null) { System.out.println("Host: " + serviceA.getHost()); System.out.println("IP: " + serviceA.getIp()); System.out.println("Desc: " + serviceA.getDesc()); } else { System.out.println("ServiceA not found in configuration"); } }
备注:内容来源于stack exchange,提问作者Vikrant

