You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot读取YML配置时Bean创建报错(空指针异常)求助

解决Spring Boot配置绑定导致的NullPointerException问题

我来帮你排查这个空指针异常,根源在于你的配置类和application.yml的结构不匹配,导致配置属性没有被正确绑定,最终在DemoService的构造函数里调用projects.get("section1")时触发了NullPointerException。

问题分析

  1. 配置类与yml结构冲突:你的application.yml中security.section1是一个包含key1/key2的对象节点,但SecurityProperties类里却同时定义了String section1字段和Map<String,Section1Properties> sec1字段,Spring无法正确解析这种冲突的结构,导致sec1始终为null。
  2. 配置绑定失败:由于结构不匹配,security.myConfig1()返回的sec1是null,赋值给projects后,调用projects.get("section1")自然会抛出空指针。

解决方案

根据你的需求,分两种场景给出修正方案:

场景1:保持现有application.yml结构不变

这种情况下,我们需要让SecurityProperties的结构和yml完全对应:

修正后的SecurityProperties类

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "security")
public class SecurityProperties implements Serializable {
    private static final long serialVersionUID = 1L;

    // 直接对应yml中的security.section1节点
    private Section1Properties section1;
    // 直接对应yml中的security.section2节点
    private Section2Properties section2;

    // Getter和Setter必须存在,Spring依赖它们完成属性绑定
    public Section1Properties getSection1() {
        return section1;
    }

    public void setSection1(Section1Properties section1) {
        this.section1 = section1;
    }

    public Section2Properties getSection2() {
        return section2;
    }

    public void setSection2(Section2Properties section2) {
        this.section2 = section2;
    }

    public static class Section1Properties {
        private String key1;
        private String key2;

        public String getKey1() {
            return key1;
        }

        public void setKey1(String key1) {
            this.key1 = key1;
        }

        public String getKey2() {
            return key2;
        }

        public void setKey2(String key2) {
            this.key2 = key2;
        }
    }

    public static class Section2Properties {
        private String key1;
        private String key2;

        public String getKey1() {
            return key1;
        }

        public void setKey1(String key1) {
            this.key1 = key1;
        }

        public String getKey2() {
            return key2;
        }

        public void setKey2(String key2) {
            this.key2 = key2;
        }
    }
}

修正后的DemoService类

@Service
public class DemoService {
    private final SecurityProperties securityProperties;

    @Autowired
    public DemoService(SecurityProperties securityProperties) {
        this.securityProperties = securityProperties;
        // 现在可以安全地访问配置属性
        String section1Key1 = securityProperties.getSection1().getKey1();
        String section1Key2 = securityProperties.getSection1().getKey2();
        
        // 可选:测试输出确认配置加载成功
        System.out.println("section1.key1: " + section1Key1);
        System.out.println("section1.key2: " + section1Key2);
    }
}

场景2:改用Map存储多个section(适合未来扩展更多section)

如果你希望用Map统一管理多个section,需要先调整yml结构,再修改配置类:

修改后的application.yml

security:
  sections:
    section1:
      key1: "value1"
      key2: "value2"
    section2:
      key1: "value1"
      key2: "value2"

修正后的SecurityProperties类

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "security")
public class SecurityProperties implements Serializable {
    private static final long serialVersionUID = 1L;

    // 用Map存储所有section,key对应section名称,value对应section的属性
    private Map<String, SectionProperties> sections = new HashMap<>();

    public Map<String, SectionProperties> getSections() {
        return sections;
    }

    public void setSections(Map<String, SectionProperties> sections) {
        this.sections = sections;
    }

    // 统一的SectionProperties类,因为section1和section2结构一致
    public static class SectionProperties {
        private String key1;
        private String key2;

        public String getKey1() {
            return key1;
        }

        public void setKey1(String key1) {
            this.key1 = key1;
        }

        public String getKey2() {
            return key2;
        }

        public void setKey2(String key2) {
            this.key2 = key2;
        }
    }
}

修正后的DemoService类

@Service
public class DemoService {
    private final Map<String, SecurityProperties.SectionProperties> sections;

    @Autowired
    public DemoService(SecurityProperties securityProperties) {
        this.sections = securityProperties.getSections();
        // 安全访问section1的属性
        String section1Key1 = sections.get("section1").getKey1();
        String section1Key2 = sections.get("section1").getKey2();
    }
}

关键注意事项

  • Spring的@ConfigurationProperties依赖标准的Getter/Setter方法来完成属性绑定,必须确保每个属性都有对应的Getter和Setter。
  • 配置类的结构必须和yml的层级结构完全对应,否则会出现绑定失败的情况。
  • 尽量避免在构造函数中直接执行复杂的业务逻辑,如果需要初始化操作,可以考虑用@PostConstruct注解,确保所有Bean都完成初始化后再执行。

内容的提问来源于stack exchange,提问作者frontdesk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:18:03