不可变@ConfigurationProperties

2022-08-31 17:20:50

是否有可能具有带有Spring Boot注释的不可变(最终)字段?下面的示例@ConfigurationProperties

@ConfigurationProperties(prefix = "example")
public final class MyProps {

  private final String neededProperty;

  public MyProps(String neededProperty) {
    this.neededProperty = neededProperty;
  }

  public String getNeededProperty() { .. }
}

到目前为止,我尝试过的方法:

  1. 创建具有两个构造函数的类的 a@BeanMyProps
    • 提供两个构造函数:空和带参数neededProperty
    • 豆子是用new MyProps()
    • 现场结果null
  2. 使用和提供豆类。@ComponentScan@ComponentMyProps
    • 结果在BeanInstantiationException -> NoSuchMethodException: MyProps.<init>()

我让它工作的唯一方法是为每个非最终字段提供getter/setter。


答案 1

从 Spring Boot 2.2 开始,终于可以定义一个用 .
文档显示了一个示例。
您只需要声明一个构造函数,其中包含要绑定的字段(而不是 setter 方式),并在类级别添加@ConstructorBinding注释以指示应使用构造函数绑定。
所以你的实际代码没有任何 setter 现在很好:@ConfigurationProperties

@ConstructorBinding
@ConfigurationProperties(prefix = "example")
public final class MyProps {

  private final String neededProperty;

  public MyProps(String neededProperty) {
    this.neededProperty = neededProperty;
  }

  public String getNeededProperty() { .. }
}

答案 2

我必须经常解决这个问题,并且我使用有点不同的方法,这允许我在类中使用变量。final

首先,我将所有配置保存在一个地方(类),例如,称为.该类具有具有特定前缀的注释。它也列在针对配置类(或主类)的注释中。ApplicationProperties@ConfigurationProperties@EnableConfigurationProperties

然后,我提供 my 作为构造函数参数,并执行对构造函数内字段的赋值。ApplicationPropertiesfinal

例:

类:

@SpringBootApplication
@EnableConfigurationProperties(ApplicationProperties.class)
public class Application {
    public static void main(String... args) throws Exception {
        SpringApplication.run(Application.class, args);
    }
}

应用属性

@ConfigurationProperties(prefix = "myapp")
public class ApplicationProperties {

    private String someProperty;

    // ... other properties and getters

   public String getSomeProperty() {
       return someProperty;
   }
}

以及具有最终属性的类

@Service
public class SomeImplementation implements SomeInterface {
    private final String someProperty;

    @Autowired
    public SomeImplementation(ApplicationProperties properties) {
        this.someProperty = properties.getSomeProperty();
    }

    // ... other methods / properties 
}

出于许多不同的原因,我更喜欢这种方法,例如,如果我必须在构造函数中设置更多属性,我的构造函数参数列表并不“庞大”,因为我总是有一个参数(在我的情况下);如果需要添加更多属性,我的构造函数保持不变(只有一个参数) - 这可能会减少其他地方的更改次数等。ApplicationPropertiesfinal

我希望这会有所帮助


推荐