• 利用 Spring Boot 中的 @ConfigurationProperties,优雅绑定配置参数


    转载:程序员自由之路

    使用 @Value("${property}") 注释注入配置属性有时会很麻烦,尤其是当你使用多个属性或你的数据是分层的时候。

    Spring Boot 引入了一个可替换的方案 —— @ConfigurationProperties 来注入属性。

    JavaBean 属性绑定#

    @Data
    @ConfigurationProperties("my.service")
    public class MyProperties {
        
        // 我们可以简单地用一个值初始化一个字段来定义一个默认值
        private boolean enabled = true;
    
        private InetAddress remoteAddress;
    
        private final Security security = new Security();
    
        @Data
        public static class Security {
    
            private String username;
    
            private String password;
            // 如果这个属性配置的话,默认是“USER”
            private List<String> roles = new ArrayList<>(Collections.singleton("USER"));
    
        }
    }
    

    在配置文件中进行如下配置:

    my:
      service:
        enabled: true
        remoteAddress: 127.0.0.1
        security:
         username: csx
         password: passwoed
         roles:
           - role1
           - role2
    

    最后生成的 Bean 的属性如下:

    {
      "enabled": true,
      "remoteAddress": "127.0.0.1",
      "security": {
        "username": "csx",
        "password": "passwoed",
        "roles": [
          "role1",
          "role2"
        ]
      }
    }
    

    以上的绑定当时需要提供默认的构造函数,以及get/setter方法。

    并且不支持 JavaBean 中的静态成员变量的数据绑定

    另外,@ConfigurationProperties 还有两个其他属性。

    @ConfigurationProperties( value = "my.service",
                              ignoreInvalidFields = false,
                              ignoreUnknownFields = false)
    

    ignoreInvalidFields:是否忽略非法值,比如将一个字符串 “foo” 赋值给 bool 值,不忽略的话会报启动异常。

    ignoreUnknownFields:对于多余的配置是否会报异常。

    构造函数绑定#

    有些情况下,我们需要绑定的 JavaBean 是不可变的(防止配置注入 Bean 以后,开发者在程序中错误地将配置改掉了)。这种情况下我们可以使用构造函数形式的绑定,只提供 getter 方法。

    @Getter
    @ConstructorBinding
    @ConfigurationProperties("my.service")
    public class MyProperties {
    
        private boolean enabled;
        private InetAddress remoteAddress;
        private final Security security;
    
        public MyProperties(boolean enabled, InetAddress remoteAddress, Security security) {
            this.enabled = enabled;
            this.remoteAddress = remoteAddress;
            this.security = security;
        }
    
        @Getter
        public static class Security {
    
            private String username;
            private String password;
            private List<String> roles;
    
            public Security(String username, String password, @DefaultValue("USER") List<String> roles) {
                this.username = username;
                this.password = password;
                this.roles = roles;
            }
        }
    }
    

    @DefaultValue 可以指定默认值。

    使用构造函数绑定的方式,只能 @EnableConfigurationProperties 或者 @ConfigurationPropertiesScan 的方式激活 Bean。而不能使用 @Component、@Bean 或者 @Import 的方式进行数据绑定。

    如果你的类有多个构造函数,可以直接指定使用哪个。

    @ConstructorBinding
    public MyProperties(boolean enabled, InetAddress remoteAddress, Security security) {
        this.enabled = enabled;
        this.remoteAddress = remoteAddress;
        this.security = security;
    }
    

    激活方式#

    方式一:添加 @Component 注解

    上面的方式需要保证 MyProperties 能被 Spring 扫到。

    @Data
    @Component
    @ConfigurationProperties("my.service")
    public class MyProperties {
        
    }
    

    方式二:通过 @Bean 方法

    @Configuration
    public class ServiceConfig {
    
        @Bean
        public MyProperties myProperties(){
            return new MyProperties();
        }
    }
    

    方式三:@EnableConfigurationProperties(推荐)

    @Configuration
    @EnableConfigurationProperties(MyProperties.class)
    public class ServiceConfig {
    
    }
    

    方式四:@ConfigurationPropertiesScan

    @SpringBootApplication
    @ConfigurationPropertiesScan({ "com.example.app", "com.example.another" })
    public class MyApplication {
    
    }
    

    怎么使用#

    我们通过配置在 Spring 容器中生成了配置 Bean,那么需要怎么使用他们呢?

    @Service
    public class MyService {
        // 依赖注入
        @Autowired
        private MyProperties properties;
    
        public void service(){
            System.out.println(properties.getRemoteAddress());
        }
    
    }
    
    @Service
    public class MyService {
    
        private MyProperties properties;
        // 通过构造函数注入,一般推荐这种方式
        public MyService(MyProperties properties) {
            this.properties = properties;
        }
    
        public void service(){
            System.out.println(properties.getRemoteAddress());
        }
    
    }
    
    

    给第三方类绑定值#

    假如某些类不是你自己开发的,你也想使用 @ConfigurationProperties 的方式给他绑定值,那么可以进行下面的方式进行配置。

    @Configuration(proxyBeanMethods = false)
    public class ThirdPartyConfiguration {
    
        @Bean
        @ConfigurationProperties(prefix = "another")
        public AnotherComponent anotherComponent() {
            return new AnotherComponent();
        }
    
    }
    

    宽松绑定原则(Relaxed Binding)#

    所谓的宽松绑定原则是指:并不是 JavaBean 中的属性必须要和配置文件中的一致才能绑定数据,context-path 也能绑定到 contextPath 属性上。下面举个列子:

    @ConfigurationProperties(prefix = "my.main-project.person")
    public class MyPersonProperties {
    
        private String firstName;
    
        public String getFirstName() {
            return this.firstName;
        }
    
        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }
    
    }
    

    下面的几种方式,都能将配置文件或者环境变量中的值绑定到 firstName 上。

    形式使用场景
    my.main-project.person.first-name 推荐使用在 .properties and .yml files.
    my.main-project.person.firstName Standard camel case syntax.
    my.main-project.person.first_name 推荐使用在 .properties and .yml files.
    MY_MAINPROJECT_PERSON_FIRSTNAME 推荐使用在系统环境变量读取配置时使用

    和 @Value 对比#

    @Value 是 Spring Framework 中的注解,而 @ConfigurationProperties 是在 Spring Boot 中引入的。

    img

    参考#

    作者:程序员自由之路

    出处:https://www.cnblogs.com/54chensongxia/p/15250479.html

    版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

  • 相关阅读:
    CODE
    JS中如何进行对象的深拷贝
    js数组操作---改变原数组和不改变原数组的方法整理
    echarts做双柱图
    如何在react中使用OrgChart?
    如何让背景透明?
    如何使用css选择器隐藏滚动条?
    input 修改placeholder中颜色和字体大小
    在input、textarea 标签的placeholder中实现换行的方法
    React Hooks异步操作防踩坑指南
  • 原文地址:https://www.cnblogs.com/yhc-love-cl/p/15251053.html
Copyright © 2020-2023  润新知