前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >@ConfigurationProperties VS @Value,你觉得哪个更好用

@ConfigurationProperties VS @Value,你觉得哪个更好用

作者头像
索码理
发布2024-07-08 16:15:42
510
发布2024-07-08 16:15:42
举报
文章被收录于专栏:索码理

实际工作中,我们经常会看到或用到@ConfigurationProperties@Value 注解来注入自定义配置属性,那它们之间有什么不同呢?本文将从松散绑定 、参数校验、SpEL表达式、元数据支持等多方面介绍两者之间的不同之处。

使用

先看一下怎么使用它们。

  1. 先自定义几个配置属性
代码语言:javascript
复制
sun-coder-note.name=索码理
sun-coder-note.en_name=sunocdernote
# 粉丝数
sun-coder-note.fansCount=10000000
# 阅读数
sun-coder-note.read-count=10000000

sun-coder-note.article.title=自定义配置@ConfigurationProperties和@Value区别
sun-coder-note.article.category=springboot系列
  1. 使用 @ConfigurationProperties 注解接收自定义属性

定义一个SunCoderNoteProperties类, 使用 @ConfigurationProperties 注解接收自定义属性

代码语言:javascript
复制
@Data
@Configuration
@ConfigurationProperties(prefix = "sun-coder-note")
public class SunCoderNoteProperties {

    /**
     * 中文名
     */
    private String name;

    /**
     * 英文名
     */
    private String enName;

    /**
     * 粉丝数
     */
    private Integer fansCount;

    /**
     * 阅读数
     */
    private Integer readCount;

    /**
     * 文章
     */
    private ArticleProperties article;
}

通常情况下,在使用 @ConfigurationProperties 注解时,只要指定prefix前缀属性即可,同时 @Configuration 也要一起使用,要不然Springboot识别不到自定义的属性。

  1. 使用 @Value 注解获取自定义属性

在属性上使用 @Value 注解 ,使用 $ 符号直接获取自定义属性名对应的值。

代码语言:javascript
复制
@Data
@Configuration
public class SunCoderNoteValueProperties {

    @Value("${sun-coder-note.name}")
    private String name;

    @Value("${sun-coder-note.en-name}")
    private String enName;

    @Value("${sun-coder-note.fans-count}")
    private Integer fansCount;

    @Value("${sun-coder-note.read-count}")
    private Integer readCount;
}

测试

上面两个属性类定义好后,通过单元测试,测试能否获取到值。

代码语言:javascript
复制
@SpringBootTest
class PropertiesApplicationTests {

    @Resource
    private SunCoderNoteProperties sunCoderNoteProperties;
    @Resource
    private SunCoderNoteValueProperties sunCoderNoteValueProperties;

    @Test
    public void testBean(){
        System.out.println(sunCoderNoteProperties);
        System.out.println();
        System.out.println(sunCoderNoteValueProperties);
    }
}

通过测试,查看控制台,可以看到两种方式都能够获取到对应的属性值。

代码语言:javascript
复制
SunCoderNoteProperties(name=索码理, enName=sunocdernote, fansCount=10000000, readCount=10000000, article=ArticleProperties(title=自定义配置@ConfigurationProperties和@Value区别, category=springboot系列))

SunCoderNoteValueProperties(name=索码理, enName=sunocdernote, fansCount=10000000, readCount=10000000)

@ConfigurationProperties和@Value区别

既然 @ConfigurationProperties@Value 都能够获取到自定义属性的值,那么它们之间有什么区别呢? 不用我说,聪明的你通过上面的使用示例也能看出一些区别,下面我会总结一下它们的区别并逐个进行介绍。

特性

@ConfigurationProperties

@Value

复杂类型封装

支持

不支持

松散绑定

支持

支持(有限制)

SpEL表达式

不支持

支持

JSR-303 数据校验

支持

不支持

元数据支持

支持

不支持

复杂类型封装

  • @ConfigurationProperties: 支持复杂类型的封装,比如上面的 ArticleProperties ,除此之外还支持列表、集合等。
  • @Value: 通常只支持简单类型的封装,不适用于复杂类型的直接注入。

松散绑定

松散绑定是一种在属性绑定时提供灵活性的机制,它允许配置文件中的属性名与Java类中的字段名之间存在一定的差异,不需要严格匹配。

松散绑定支持多种不同的命名风格,包括驼峰式短横线隔开式下划线表示法 以及大写格式

  • 短横线隔开式:建议在.properties和 YAML配置文件中使用。
  • 下划线表示法:可以选择在.properties和 YAML配置文件中使用。
  • 大写格式:建议在使用系统环境变量时使用。

下面举例说明一下:

示例

以使用了 @ConfigurationProperties 注解的SunCoderNoteProperties类的enName属性为例。

  • 在配置文件中,可以使用以下任意一种形式来配置该属性:
    • sun-coder-note.enName=sunocdernote
    • sun-coder-note.en-name=sunocdernote
    • sun-coder-note.en_name=sunocdernote
    • sun-coder-note.EN_NAME=sunocdernote

SpringBoot的松散绑定机制都可以自动将这些配置映射到SunCoderNoteProperties类的enName属性上。

但对于 @Value注解来说,它是有一定的限制的,比如下面3种命名方式:

  • sun-coder-note.en-name=sunocdernote
  • sun-coder-note.en_name=sunocdernote
  • sun-coder-note.EN_NAME=sunocdernote

如果这样取值 @Value("${sun-coder-note.enName}") ,你会发现不仅取不到值,还会报错。

虽然松散绑定提供了很大的灵活性,但在实际应用中,建议尽量保持配置文件中的命名风格一致,以便更容易地理解和维护配置文件。

元数据支持

所谓元数据指的是在项目使用了 @ConfigurationProperties 注解时,在编译过程中由 SpringBoot 自动生成的文件的 spring-configuration-metadata.json文件。该元数据文件主要用于为应用程序中的配置文件( application.propertiesapplication.yml)属性提供详细的元数据信息,如属性的名称、数据类型、描述、默认值和废弃信息等。

下面用一个简单示例演示一下元数据的生成:

  1. 引入 spring-boot-configuration-processor Springboot版本是3.1.5 ,不引入不会生成元数据文件
代码语言:javascript
复制
<dependency>
   <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
  1. 编译项目 项目编译完成之后,在META-INF文件夹下可以看到 spring-configuration-metadata.json

spring-configuration-metadata.json具体格式如下:

代码语言:javascript
复制
{
  "groups": [
    {
      "name": "sun-coder-note",
      "type": "site.suncodernote.properties.SunCoderNoteProperties",
      "sourceType": "site.suncodernote.properties.SunCoderNoteProperties"
    }
  ],
  "properties": [
    {
      "name": "sun-coder-note.article",
      "type": "site.suncodernote.properties.ArticleProperties",
      "description": "文章",
      "sourceType": "site.suncodernote.properties.SunCoderNoteProperties"
    },
    {
      "name": "sun-coder-note.en-name",
      "type": "java.lang.String",
      "description": "英文名",
      "sourceType": "site.suncodernote.properties.SunCoderNoteProperties"
    },
    {
      "name": "sun-coder-note.fans-count",
      "type": "java.lang.Integer",
      "description": "粉丝数",
      "sourceType": "site.suncodernote.properties.SunCoderNoteProperties"
    },
    {
      "name": "sun-coder-note.name",
      "type": "java.lang.String",
      "description": "中文名",
      "sourceType": "site.suncodernote.properties.SunCoderNoteProperties"
    },
    {
      "name": "sun-coder-note.read-count",
      "type": "java.lang.Integer",
      "description": "阅读数",
      "sourceType": "site.suncodernote.properties.SunCoderNoteProperties"
    }
  ],
  "hints": []
}

SpEL表达式

SpEL表达式(Spring Expression Language) 是Spring框架中提供的一种强大的表达式语言,它用于在运行时查询和操作对象。

下面举个简单的示例看下 @Value 注解结合SpEL表达式的使用:

代码语言:javascript
复制
@Data
@Configuration
public class SunCoderNoteValueProperties {

    /**
     * 如果sun-coder-note.name自定义属性不存在,设置name默认值为suncodernote
     */
    @Value("${sun-coder-note.name:suncodernote}")
    private String name;

    /**
     *  enName属性的值取site.suncodernote.validation.GenderEnum枚举类的MALE常量的name值
     */
    @Value("#{T(site.suncodernote.validation.GenderEnum).MALE.name()}")
    private String enName;


    /**
     * 如果sun-coder-note.fansCount的值小于1000,就让该值等于10,否则取该值
     */
    @Value("#{${sun-coder-note.fansCount} < 1000 ? 10 : ${sun-coder-note.fansCount}}")
    private Integer fansCount;

    @Value("${sun-coder-note.read-count}")
    private Integer readCount;
}

JSR-303 数据校验

之前的文章《初探Springboot 参数校验》中有介绍参数校验,感兴趣的可以去看看。

@ConfigurationProperties 注解标记的配置类中也是支持参数校验的,只需要在 @Validated ,然后在对应的属性上加上要约束的注解即可。

代码语言:javascript
复制
@Data
@Configuration
@ConfigurationProperties(prefix = "sun-coder-note")
@Validated
public class SunCoderNoteProperties {}

以上就是 @ConfigurationProperties@Value 的区别。

总结

如果需要注入大量相关配置项,并且这些配置项有嵌套的结构或者集合形式,推荐使用 @ConfigurationProperties。 如果只是少量的配置项,或者希望使用SpEL表达式时,可以使用 @Value注解。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 索码理 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用
    • 测试
    • @ConfigurationProperties和@Value区别
      • 复杂类型封装
        • 松散绑定
          • 元数据支持
            • SpEL表达式
              • JSR-303 数据校验
              • 总结
              相关产品与服务
              腾讯云服务器利旧
              云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档