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

Spring Boot中含final字段且无默认构造函数的Bean初始化方案

解决Spring Boot中初始化含final字段且无默认构造函数类的ConfigurationProperties Map问题

这个问题我之前帮不少开发者解决过,刚好是Spring Boot处理不可变配置类的典型场景——既要保持SomeClass的不可变性(全final字段),又要让@ConfigurationProperties能正确初始化它的Map实例,给你两个可行的方案,优先推荐第一种,简单又符合最佳实践:


方案一:使用@ConstructorBinding(Spring Boot 2.2+ 推荐)

Spring Boot 2.2之后专门引入了@ConstructorBinding注解来支持不可变配置类,完美适配你的场景,不需要默认构造函数,直接通过带参构造完成字段初始化。

步骤1:修改SomeClass添加@ConstructorBinding

import org.springframework.boot.context.properties.ConstructorBinding;

@ConstructorBinding
public class SomeClass {
    private final int field1;
    private final String field2;

    // 仅保留带参构造,参数名要和配置文件中的key对应
    public SomeClass(int field1, String field2) {
        this.field1 = field1;
        this.field2 = field2;
    }

    // 只需要getter方法,不需要setter(final字段无法修改)
    public int getField1() {
        return field1;
    }

    public String getField2() {
        return field2;
    }
}

步骤2:配置SomeConfigurationProperties

确保开启配置属性支持,两种方式任选其一:

  • 方式A:在配置类上添加@EnableConfigurationProperties
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "some")
public class SomeConfigurationProperties {
    private Map<String, SomeClass> map = new HashMap<>();

    // 仅需要getter方法,Spring会自动绑定Map内容
    public Map<String, SomeClass> getMap() {
        return map;
    }
}
  • 方式B:直接给SomeConfigurationProperties添加@Component注解(适合自动扫描的场景)

步骤3:配置文件示例(application.yml)

按照层级结构编写配置,Spring会自动通过构造函数映射字段:

some:
  map:
    first-entry:
      field1: 123
      field2: "first-value"
    second-entry:
      field1: 456
      field2: "second-value"

注意:如果你的项目编译时没有保留参数名(比如没用Java 8+的-parameters编译参数),可以给构造函数参数添加@JsonProperty("field1")来明确对应配置key,避免绑定失败。


方案二:自定义Converter(适配Spring Boot 2.2以下版本)

如果你的Spring Boot版本低于2.2,无法使用@ConstructorBinding,可以通过自定义类型转换器来实现Map到SomeClass的转换。

实现自定义转换器

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.util.Map;

@Component
public class SomeClassConverter implements Converter<Map<String, Object>, SomeClass> {
    @Override
    public SomeClass convert(Map<String, Object> source) {
        // 手动处理配置中的字段映射,注意类型转换
        int field1 = ((Number) source.get("field1")).intValue();
        String field2 = (String) source.get("field2");
        return new SomeClass(field1, field2);
    }
}

注册这个转换器后,Spring在处理@ConfigurationProperties中的Map时,会自动调用它把配置中的键值对转换成SomeClass实例。


关键说明

  • 方案一的@ConstructorBinding是Spring官方推荐的不可变配置类解决方案,代码更简洁,也符合不可变对象的设计原则。
  • 两种方案都不需要XML配置,完全适配Spring Boot的注解驱动开发模式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:18:56