Spring boot 应用程序属性中的不可变列表

问题描述 投票:0回答:3

我在从属性文件(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;

}

但我希望该列表不可修改。此列表中的后续代码更改可能会在流程中产生非常严重的错误。所以我认为这样的东西会起作用,但事实并非如此:

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

    private final List<String> identifiers;

    private final boolean disabled;

    private final int number;

    @ConstructorBinding
    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;
    }
}

如果我将 @ConstructorBinding 添加到我得到的类中:

  Cannot bind @ConfigurationProperties for bean 'DeviceConfiguration'. 
  Ensure that @ConstructorBinding has not been applied to regular bean

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

  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

我该如何解决这个问题?

谢谢!

巴特

java spring-boot properties
3个回答
0
投票

您使用

@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;
    }
}

0
投票

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

public void setIdentifiers(List<String> identifiers) {
    this.identifiers = Collections.unmodifiableList(identifiers);
}

这意味着 DeviceConfiguration 本身不是不可变的,因为您必须删除标识符列表的 Final 并公开 mutator setter 方法,但您仍然会实现 List 不可变的事实,并且它是在 setter 中完成的,它只会执行一次,这与每次在 getter 中将标识符包装在新的不可修改列表中不同。


0
投票

我在 Spring 3.1.4 中面临同样的问题,在一个非常相似的类中。

问题是

@ConstructorBinding
不能很好地处理不可变的属性(在本例中是不可修改的列表),并且它需要可变的属性。

已向 Spring 开发人员报告

© www.soinside.com 2019 - 2024. All rights reserved.