利用 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 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 roles;

        public Security(String username, String password, @DefaultValue("USER") List 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 中引入的。

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

参考

Original: https://www.cnblogs.com/54chensongxia/p/15250479.html
Author: 程序员自由之路
Title: 利用 Spring Boot 中的 @ConfigurationProperties,优雅绑定配置参数

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/541898/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Java线程处理Future

    ExecutorService service = Executors.newCachedThreadPool(); Future future = service.submit(…

    Java 2023年5月29日
    070
  • Java开发笔记(一百四十七)通过JDBC管理数据库

    前面介绍了如何通过JDBC获取数据库连接,可是Connection对象不能直接执行SQL语句,需要引入Statement报告对象才能操作SQL。Statement对象由Connec…

    Java 2023年6月6日
    095
  • JavaScript

    什么是JavaScript 一、概述 JavaScript是一门世界上最流行的脚本语言 一个合格的后端人员,必须要精通JavaScript 快速入门 一、引入JavaScript …

    Java 2023年6月6日
    0130
  • Java 学习大纲

    1.java基础 1.1 Collection和Map(1)掌握Collection和Map的继承体系(2)掌握ArrayList,LinkedList,Vector,Stack,…

    Java 2023年5月29日
    066
  • 在 IconFont 上获取图标资源的操作方法与感悟

    如何在 IconFont 上获取图标资源 阿里巴巴矢量图标库网站(https://www.iconfont.cn/)上提供了非常丰富的图标资源,包括 SVG、AI、PNG、字体图标…

    Java 2023年6月16日
    0106
  • Spring-cloud-alibaba-nacos(配置中心-多配置文件配置)快速入门(三)

    上一篇按照环境隔离了命名空间和开发组,这篇就按照服务来划分一下 1、多配置文件 配置bootstrap.yaml spring: cloud: nacos: config: ser…

    Java 2023年6月5日
    0102
  • 搭建 vue-cli 和 引入 Element-ui 最完整的入门例子(手把手)

    搭建 vue-cli 脚手架 安装 git 安装 node 并配置环境变量,使用 zip 版本 检查 node 是否安装成功 node -v 使用淘宝镜像 npm config s…

    Java 2023年6月5日
    0151
  • 基于Nacos实现GateWay动态路由功能

    开发环境: SpringBoot: 2.6.5 SpringCloud: 2021.0.0 SpringCloudAlibaba: 2021.0.1.0 Nacos: 2.1.0 …

    Java 2023年6月5日
    084
  • 内存分析器 (MAT)

    内存分析器 (MAT) 1.1 MAT介绍 MAT是Memory Analyzer tool的缩写。指分析工具。 1.2 MAT作用 Eclipse Memory Analyzer…

    Java 2023年6月8日
    073
  • java技术整理1

    一、基本 1.hashmap: 1.1 转红黑树条件:a.数组长度大于等于64(默认16,要经过2次扩容–当达到16*默认扩容因子0.75=12就扩容)b.链表长度大于…

    Java 2023年6月13日
    0122
  • docker安装Jenkins

    背景:内网打包纯手工,每次打包、部署很烦 需求:傻瓜式操作、持续集成 方法: 一、安装Jenkins 1、拉取镜像 docker pull jenkins/jenkins 2、拉取…

    Java 2023年6月8日
    096
  • 【米哈游2023届秋招】开启【校招唯一专属内推码EYTUC】

    爆个猛料 很猛的 米哈游7月 又有新岗位啦!!!!不打卡弹性工作。抓紧金7银8面试机会,年中岗位多、急、需求量大,offer流程快。现招:技术(算法、前端、后台、大数据、安卓ios…

    Java 2023年6月8日
    0111
  • 纯注解开发模式

    定义bean: 纯注解开发模式: 用SpringConfig类来代替applicationContext.xml配置文件,利用注解@configuration代表了xml里的基本配…

    Java 2023年6月16日
    091
  • 理解设计模式之“道”

    在什么维度变化,就在什么维度抽象。 引语 设计模式是进入系统设计殿堂的入门明灯。我也是通过学习设计模式开始接触软件设计的。许多业务开发同学应该也听说过设计模式,了解和学习过部分设计…

    Java 2023年6月9日
    095
  • 二、冯·诺依曼结构与快捷键的使用

    一、冯·诺依曼结构 二、快捷键的使用 Ctrl+A:全选Ctrl+C:复制Ctrl+V:粘贴Ctrl+X:剪切Ctrl+Z:撤销Ctrl+S:保存Alt+F4:关闭窗口Shift+…

    Java 2023年6月5日
    076
  • 使用spire.doc导出支持编辑Latex公式的标准格式word

    背景 之前有的教辅标注需求,在导出题库的时候希望顺便导出可以查看word,方便线下预览成品效果,因为只是用来预览并且为了沿用前端的样式,当时方案就是直接生成html,写个word的…

    Java 2023年6月7日
    072
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球