Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 不可变@ConfigurationProperties_Java_Spring_Spring Boot_Properties File - Fatal编程技术网

Java 不可变@ConfigurationProperties

Java 不可变@ConfigurationProperties,java,spring,spring-boot,properties-file,Java,Spring,Spring Boot,Properties File,是否可以使用Spring Boot的@ConfigurationProperties注释设置不可变(最终)字段?下面的例子 @ConfigurationProperties(prefix = "example") public final class MyProps { private final String neededProperty; public MyProps(String neededProperty) { this.neededProperty = neede

是否可以使用Spring Boot的
@ConfigurationProperties
注释设置不可变(最终)字段?下面的例子

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

  private final String neededProperty;

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

  public String getNeededProperty() { .. }
}
到目前为止我已经尝试过的方法:

  • 使用两个构造函数创建
    MyProps
    类的
    @Bean
    • 提供两个构造函数:空的和带有
      neededProperty
      参数的
    • bean是使用
      newmyprops()创建的。
    • 字段中的结果为
      null
  • 使用
    @ComponentScan
    @Component
    提供
    MyProps
    bean。
    • 结果导致
      BeanInstantiationException
      ->
      NoSuchMethodException:MyProps。

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

    我必须经常解决这个问题,我使用一种稍微不同的方法,这允许我在类中使用
    final
    变量

    首先,我将所有配置保存在一个单独的位置(类),比如称为
    ApplicationProperties
    。该类具有带有特定前缀的
    @ConfigurationProperties
    注释。它还列在配置类(或主类)的
    @EnableConfigurationProperties
    注释中

    然后,我提供我的
    ApplicationProperties
    作为构造函数参数,并对构造函数中的
    final
    字段执行赋值

    例如:

    主类类:

    @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 
    }
    
    出于许多不同的原因,我更喜欢这种方法,例如,如果我必须在构造函数中设置更多属性,那么我的构造函数参数列表并不“庞大”,因为我总是有一个参数(
    ApplicationProperties
    );如果需要添加更多的
    final
    属性,我的构造函数将保持不变(只有一个参数)-这可能会减少其他地方的更改数量等


    我希望这最终会有所帮助,如果你想要一个不可变的对象,你也可以“破解”setter

    @ConfigurationProperties(prefix = "myapp")
    public class ApplicationProperties {
        private String someProperty;
    
        // ... other properties and getters
    
        public String getSomeProperty() {
           return someProperty;
        }
    
        public String setSomeProperty(String someProperty) {
          if (someProperty == null) {
            this.someProperty = someProperty;
          }       
        }
    }
    
    显然,如果属性不仅仅是一个字符串,也就是一个可变对象,事情就更复杂了,但这是另一回事

    更好的是,您可以创建一个配置容器

    @ConfigurationProperties(prefix = "myapp")
    public class ApplicationProperties {
       private final List<MyConfiguration> configurations  = new ArrayList<>();
    
       public List<MyConfiguration> getConfigurations() {
          return configurations
       }
    }
    
    和application.yml as

    myapp:
      configurations:
        - someProperty: one
        - someProperty: two
        - someProperty: other
    

    您可以通过
    @Value
    注释设置字段值。这些可以直接放置在字段上,不需要任何设置程序:

    @Component
    public final class MyProps {
    
      @Value("${example.neededProperty}")
      private final String neededProperty;
    
      public String getNeededProperty() { .. }
    }
    
    这种方法的缺点是:

    • 您需要在每个字段上指定完全限定的属性名
    • 验证不起作用(参见)

    我的想法是通过内部类封装属性组,并仅使用getter公开接口

    属性文件:

    myapp.security.token-duration=30m
    myapp.security.expired-tokens-check-interval=5m
    
    myapp.scheduler.pool-size=2
    
    代码:


    从SpringBoot2.2开始,最终可以定义一个用
    @ConfigurationProperties

    修饰的不可变类 显示了一个示例。
    您只需使用要绑定的字段(而不是setter方式)声明一个构造函数,并在类级别添加注释以指示应使用构造函数绑定。
    因此,没有任何setter的实际代码现在就可以了:

    @ConstructorBinding
    @ConfigurationProperties(prefix = "example")
    public final class MyProps {
    
      private final String neededProperty;
    
      public MyProps(String neededProperty) {
        this.neededProperty = neededProperty;
      }
    
      public String getNeededProperty() { .. }
    }
    

    使用Lombok注释,代码如下所示:

    @ConfigurationProperties(prefix = "example")
    @AllArgsConstructor
    @Getter
    @ConstructorBinding
    public final class MyProps {
    
      private final String neededProperty;
    
    }
    
    此外,如果要直接自动关联此属性类,而不使用
    @Configuration
    类和
    @EnableConfigurationProperties
    ,则需要将
    @ConfigurationPropertiesScan
    添加到用
    @SpringBootApplication
    注释的主应用程序类中


    请参阅此处的相关文档:

    使用与

    但是您可以使用
    RequiredArgsConstructor
    而不是
    AllArgsConstructor

    考虑以下
    应用程序。属性

    myprops.example.firstName=Peter
    myprops.example.last name=Pan
    myprops.example.age=28
    
    注意:使用与属性一致的方法,我只是想说明这两种方法都是正确的(
    fistName
    last name


    获取属性的Java类

    @Service
    public class SomeImplementation implements SomeInterface {
        private final String someProperty;
    
        @Autowired
        public SomeImplementation(ApplicationProperties properties) {
            this.someProperty = properties.getSomeProperty();
        }
    
        // ... other methods / properties 
    }
    
    @Getter
    @构造绑定
    @所需参数构造函数
    @ConfigurationProperties(前缀=“myprops.example”)
    公共类舞台图
    {
    私有最终字符串名;
    私有最终整数lastName;
    私人最终整数年龄;
    // ...
    }
    

    此外,还必须向构建工具添加依赖项

    格雷德尔先生

    pom.xml

    
    org.springframework.boot
    spring引导配置处理器
    ${spring.boot.version}
    

    如果您为您的配置提供更精确的描述,请考虑在目录<代码> > SRC/main /Realth/Meta AF < < /P>中创建文件<代码>附加Spring配置元数据.JSON<代码>。

    {
    “财产”:[
    {
    “name”:“myprops.example.firstName”,
    “类型”:“java.lang.String”,
    “描述”:“此web服务的产品所有者的名字。”
    },
    {
    “name”:“myprops.example.lastName”,
    “类型”:“java.lang.String”,
    “描述”:“此web服务的产品所有者的姓氏。”
    },
    {
    “name”:“myprops.example.age”,
    “类型”:“java.lang.Integer”,
    “描述”:“自开发开始以来,此web服务的当前时代。”
    }
    }
    
    (清理并编译以生效)


    至少在IntelliJ中,当您将鼠标悬停在
    应用程序.propoerties
    中的属性上时,您可以获得自定义属性的清晰定价。这对其他开发人员非常有用


    这为我的属性提供了一个简洁的结构,我正在为spring服务。

    据我所知,您试图做的事情不会在开箱即用的情况下完成。这很遗憾。当然,我可以用纯spring b来完成
    @ConfigurationProperties(prefix = "example")
    @AllArgsConstructor
    @Getter
    @ConstructorBinding
    public final class MyProps {
    
      private final String neededProperty;
    
    }
    
        annotationProcessor('org.springframework.boot:spring-boot-configuration-processor')