【问题标题】:Why does @ConfigurationProperties need getters?为什么@ConfigurationProperties 需要getter?
【发布时间】:2021-03-27 13:11:37
【问题描述】:

我在 SpringBoot 中发现了一个奇怪的行为。

在一个 yml 文件中,我有以下配置:

main:
  record-id:
    start-position: 1
    value: 1
    enabled: true
  record-name:
    start-position: 2
    value: main
    enabled: true
  invented:
    start-position: 3
    value: 01012020
    enabled: false

这些是它的类:

public class FieldType {
  private Integer startPosition;
  private String value;
  private Boolean enabled;
  getters/setters
}

@Component
@ConfigurationProperties(prefix = "main")
public class Main {
  private FieldType recordId;
  private FieldType recordName;
  private FieldType invented;
  getters/setters <-- sometimes without getters
}

如您所见,主类具有 @ConfigurationProperties 注释以将 yml 中的属性加载到该 bean 中。

这是我发现的:

  1. 如果我不为 ma​​in 类中的字段提供 getter,那么主调用中的字段有时会保持为空,因此不会启动
  2. 如果我重新启动 SpringBoot,那么随机其他(1 个或多个)字段保持为空,因此未启动
  3. 如果我重新启动 SpringBoot n 次,那么,一次又一次,随机字段保持为空
  4. 如果我为主类中的字段提供getter,那么无论我重启SpringBoot多少次,所有字段都将始终从tye yml文件中实例化

这是为什么?为什么 SpringBoot 需要在 yml 中表示属性的字段的 getter?

【问题讨论】:

    标签: java spring-boot yaml instantiation configurationproperties


    【解决方案1】:

    你不需要getter来绑定属性,如果你使用默认构造函数,你需要setter来绑定属性,docs

    如果嵌套 POJO 属性已初始化(如前面示例中的 Security 字段),则不需要 setter。如果您希望 binder 使用其默认构造函数动态创建实例,则需要一个 setter。

    如果您在 Main 类中初始化 FieldType,那么您也不需要设置器

    @Component
    @ConfigurationProperties(prefix = "main")
    public class Main {
        private FieldType recordId = new FieldType();
        private FieldType recordName = new FieldType();
        private FieldType invented = new FieldType();
    
     }
    

    你也可以通过完全避免 setter 来使用Constructor binding

    public class FieldType {
       private Integer startPosition;
       private String value;
       private Boolean enabled;
       
       public FieldType(Integer startPosition, String value, Boolean enabled) {
             this.startPosition = startPosition;
             this.value = value;
             this.enabled = enabled
    
      }
    
      @ConstructorBinding
      @ConfigurationProperties(prefix = "main")
      public class Main {
           private FieldType recordId;
           private FieldType recordName;
           private FieldType invented;
    
      public Main(FieldType recordId,FieldType recordName,FieldType invented) {
           this.recordId = recordId;
           this.recordName = recordName;
           this.invented = invented;
    
      }
    

    只是关于构造函数绑定的注释

    要使用构造函数绑定,必须使用@EnableConfigurationProperties 或配置属性扫描来启用类。您不能对由常规 Spring 机制创建的 bean 使用构造函数绑定(例如,@Component beans、通过 @Bean 方法创建的 beans 或使用 @Import 加载的 beans)

    【讨论】:

    • 是的,这也是我的想象,但在调试过程中我得到了不同的结果
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 2017-03-20
    • 2017-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多