Java 应用程序属性中的Spring引导不可变列表

Java 应用程序属性中的Spring引导不可变列表,java,spring-boot,properties,Java,Spring Boot,Properties,从属性文件(yaml文件)创建不可修改的列表时,我有点不知所措。这项工作: @Getter @ConfigurationProperties(prefix = "device") @Configuration public class DeviceConfiguration { private final List<String> identifiers; @Value("${device.somekey.disabled:false

从属性文件(yaml文件)创建不可修改的列表时,我有点不知所措。这项工作:

@Getter
@ConfigurationProperties(prefix = "device")
@Configuration
public class DeviceConfiguration {

    private final List<String> identifiers;

    @Value("${device.somekey.disabled:false}")
    private final boolean disabled;

    @Value("${device.someotherkey.number}")
    private final int number;

}
如果我将@ConstructorBinding添加到构造函数(如示例所示),我会得到:

我该如何解决这个问题

谢谢


Bart

您以错误的方式使用了
@ConstructorBinding
。描述了正确的用法。注释需要放置在类级别上:

@Getter
@ConstructorBinding
@ConfigurationProperties(prefix = "device")
public class DeviceConfiguration {

    private final List<String> identifiers;

    private final boolean disabled;

    private final int number;

    public DeviceConfiguration(final List<String> identifiers,
                               @Value("${device.somekey.disabled:false}") final boolean disabled,
                               @Value("${device.someotherkey.number}") final int number) {
        this.identifiers = Collections.unmodifiableList(identifiers);
        this.userkeySigningDisabled = userkeySigningDisabled;
        this.number = number;
    }
}
@Getter
@构造绑定
@配置属性(前缀=“设备”)
公共类设备配置{
私人最终名单标识符;
禁用私有最终布尔值;
私人最终整数;
公共设备配置(最终列表标识符,
@值(“${device.somekey.disabled:false}”)最终布尔值已禁用,
@值(“${device.someotherkey.number}”)最终整数){
this.identifiers=Collections.unmodifiableList(标识符);
this.userkeySigningDisabled=userkeySigningDisabled;
这个数字=数字;
}
}

您可以拥有一个重载的setter方法,Spring将使用该方法进行绑定。在setter中,您可以执行与构造函数示例中相同的操作,如

public void setIdentifiers(List<String> identifiers) {
    this.identifiers = Collections.unmodifiableList(identifiers);
}
public void setIdentifiers(列表标识符){
this.identifiers=Collections.unmodifiableList(标识符);
}

这意味着DeviceConfiguration本身不会是不可变的,因为您必须删除标识符列表的final并公开mutator setter方法,但您仍然可以实现列表是不可变的事实,正如setter中所做的那样,它只执行一次,不像每次在getter中都将标识符包装到新的不可修改列表中。

您面临的错误是什么?好的,我在描述中添加了异常。为什么不简单地将
标识符包装到getter中的不可修改列表中呢?另外,我希望Spring能够为属性创建一个不可修改的列表,你确定不是这样吗?@crizzis每次调用getter时,你都会创建一个新的数组对象,这似乎不是编码该属性的最佳方式列表将有多少个元素?你打算给这位能手打多少次电话?一份列表的副本只占用其元素引用的空间。我尝试过这样做(参见原始问题)。然后我得到了这个错误:无法为bean“DeviceConfiguration”绑定@ConfigurationProperties。确保@ConstructorBinding未应用于常规bean,因为它会告诉您无法将注释应用于常规bean,这意味着您应该删除在此处设置注释的@Configuration。是的,我明白了。但有趣的是,如果您不使用@ConstructorBinding,那么就允许它将@ConfigurationProperties和@Configuration组合在一起(并且可以工作)。我不知道为什么。
  Failed to bind properties under 'device' ...
  Property: device.identifiers[5]
  Value: SomeValue
  Origin: class path resource [application.yaml] - 424:7
  Reason: No setter found for property: identifiers
@Getter
@ConstructorBinding
@ConfigurationProperties(prefix = "device")
public class DeviceConfiguration {

    private final List<String> identifiers;

    private final boolean disabled;

    private final int number;

    public DeviceConfiguration(final List<String> identifiers,
                               @Value("${device.somekey.disabled:false}") final boolean disabled,
                               @Value("${device.someotherkey.number}") final int number) {
        this.identifiers = Collections.unmodifiableList(identifiers);
        this.userkeySigningDisabled = userkeySigningDisabled;
        this.number = number;
    }
}
public void setIdentifiers(List<String> identifiers) {
    this.identifiers = Collections.unmodifiableList(identifiers);
}