解读@ConfigurationProperties和@value的区别

2025-05-23 15:50

本文主要是介绍解读@ConfigurationProperties和@value的区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《解读@ConfigurationProperties和@value的区别》:本文主要介绍@ConfigurationProperties和@value的区别及说明,具有很好的参考价值,希望对大家...

在 Spring Boot 中,@ConfigurationProperties@Value 都是用于注入配置值的注解,但它们的设计目标、使用场景和功能有显著差异。

以下是它们的核心区别和适用场景:

1. 功能对比

特性@ConfigurationProperties@Value
作用范围批量绑定配置文件中的 一组相关属性 到 Bean 的字段。注入 单个属性值 到字段或参数。
松散绑定支持松散绑定(如 myProp、my-prop、MY_PROP)。不支持,属性名必须严格匹配。
类型安全基于 类型安全的配置绑定(字段类型自动转换)。需要手动处理类型转换,如 @Value("${port}") int port。
SpEL 表达式不支持 SpEL 表达式。支持 SpEL 表达式(如 @Value("#{systemProperties['user']}"))。
默认值通过字段初始化设置默认值(如 private String name = "default";)。可在占位符中指定默认值(如 @Value("${name:default}"))。
验证支持支持 jsR-30www.chinasem.cn3 验证(如 @NotNull、@Size)。不支持 验证注解。
复杂对象绑定支持嵌套对象、集合、Map 等复杂结构的绑定。仅支持简单类型(需手动拆分复杂结构)。

2. 使用场景对比

@ConfigurationProperties

适用场景

  • 需要将 一组相关的配置属性 绑定到一个对象(如数据库配置、第三方服务配置)。
  • 需要类型安全、自动转换和松散绑定。
  • 需要支持嵌套对象或集合类型(如 ListMap)。

示例一

  // 配置类定义
  @Component
  @ConfigurationProperties(prefix = "app.datasource")
  public class DataSourceConfig {
      private String url;
      private String username;
http://www.chinasem.cn      private int maxPoolSize;
      // GeChina编程tters and Setters
  }
  
// 业务类调用
@Service
public class DataSourceSeChina编程rvice {
    @Autowired
    private DataSourceConfig dataConfig; // 直接注入配置对象

    public void connect() {
        System.out.println("Connecting to: " + dataConfig.getUrl() + ":" + dataConfig.getUsername());
    }
}

对应 application.properties

 # application.properties
 app.datasource.url=jdbc:mysql://localhost:3306/db
 app.datasource.username=power
 app.datasource.max-pool-size=10

对应 application.yml:

app:
  datasource:
    url: jdbc:mysql://localhost:3306/db
    username: power
   maxPoolSize: 10

示例二

  • 通过 @EnableConfigurationProperties 显式启用‌

‌步骤‌:

  • 在配置类或主启动类上使用 @EnableConfigurationProperties 注解,手动注册配置类14。
  • 通过构造函数或 @Autowired 注入配置对象。

‌代码示例‌:

/ 配置类定义(无需 @Component)
@ConfigurationProperties(prefix = "app.mail")
public class MailConfig {
    private String host;
    private int port;
    // getter/setter
}

// 主启动类显式启用
@SpringBootApplication
@EnableConfigurationProperties(MailConfig.class)
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

// 业务类调用(构造器注入)
@Service
public class MailService {
    private final MailConfig mailConfig;

    public MailService(MailConfig mailConfig) {
        this.mailConfig = mailConfig;
    }
}

@Value

适用场景

  • 注入 单个简单值(如开关标志、端口号)。
  • 需要动态计算值(使用 SpEL 表达式)。
  • 临时调试或快速原型开发。

示例

@Component
public class MyService {
    @Value("${app.feature.enabled:false}")
    private boolean featureEnabled;

    @Value("#{systemProperties['user.timezone']}")
    private String timezone;
}

3. 核心区别详解

(1) 类型安全与松散绑定

@ConfigurationProperties

  • 自动将配置文件中的属性转换为字段类型(如 StringintList)。
  • 支持松散绑定(属性名不严格匹配),例如 myPropmy-propMY_PROP 都会匹配到字段 myProp

@Value

  • 需要手动处理类型转换(如 @Value("${port}") int port)。
  • 属性名必须严格匹配,否则注入失败。

(2) 复杂对象支持

@ConfigurationProperties

支持嵌套对象和集合:

app:
  servers:
    - name: server1
      ip: 192.168.1.1
    - name: server2
      ip: 192.168.1.2
@ConfigurationProperties(prefix = "app编程China编程")
public class AppConfig {
    private List<Server> servers;
    // Getters and Setters
}

@Value

需要手动拆分复杂结构:

@Value("${app.servers[0].name}")
private String server1Name;

(3) 验证与默认值

@ConfigurationProperties

结合 @Validated 实现字段验证:

@ConfigurationProperties(prefix = "app")
@Validated
public class AppConfig {
    @NotNull
    private String name;
    @Min(1)
    private int maxConnections;
}

@Value

直接在占位符中设置默认值:

@Value("${app.name:DefaultApp}")
private String appName;

4. 如何选择?

场景推荐注解
需要绑定一组相关配置@ConfigurationProperties
需要注入单个简单值@Value
需要支持松散绑定或复杂结构@ConfigurationProperties
需要使用 SpEL 动态计算值@Value
需要类型安全与 JSR-303 验证@ConfigurationProperties

总结

@ConfigurationProperties

适合 集中管理复杂配置,提供类型安全、松散绑定和验证支持,是 Spring Boot 推荐的配置注入方式。

@Value

适合 快速注入简单值或动态计算值,灵活性高但缺乏类型安全和批量绑定能力。

根据实际需求选择合适的注解,优先使用 @ConfigurationProperties 以提高代码的可维护性和健壮性。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持China编程(www.chinasem.cn)。

这篇关于解读@ConfigurationProperties和@value的区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1154752

相关文章

Go之errors.New和fmt.Errorf 的区别小结

《Go之errors.New和fmt.Errorf的区别小结》本文主要介绍了Go之errors.New和fmt.Errorf的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考... 目录error的基本用法1. 获取错误信息2. 在条件判断中使用基本区别1.函数签名2.使用场景详细对

Redis中哨兵机制和集群的区别及说明

《Redis中哨兵机制和集群的区别及说明》Redis哨兵通过主从复制实现高可用,适用于中小规模数据;集群采用分布式分片,支持动态扩展,适合大规模数据,哨兵管理简单但扩展性弱,集群性能更强但架构复杂,根... 目录一、架构设计与节点角色1. 哨兵机制(Sentinel)2. 集群(Cluster)二、数据分片

一文带你迅速搞懂路由器/交换机/光猫三者概念区别

《一文带你迅速搞懂路由器/交换机/光猫三者概念区别》讨论网络设备时,常提及路由器、交换机及光猫等词汇,日常生活、工作中,这些设备至关重要,居家上网、企业内部沟通乃至互联网冲浪皆无法脱离其影响力,本文将... 当谈论网络设备时,我们常常会听到路由器、交换机和光猫这几个名词。它们是构建现代网络基础设施的关键组成

redis和redission分布式锁原理及区别说明

《redis和redission分布式锁原理及区别说明》文章对比了synchronized、乐观锁、Redis分布式锁及Redission锁的原理与区别,指出在集群环境下synchronized失效,... 目录Redis和redission分布式锁原理及区别1、有的同伴想到了synchronized关键字

C语言自定义类型之联合和枚举解读

《C语言自定义类型之联合和枚举解读》联合体共享内存,大小由最大成员决定,遵循对齐规则;枚举类型列举可能值,提升可读性和类型安全性,两者在C语言中用于优化内存和程序效率... 目录一、联合体1.1 联合体类型的声明1.2 联合体的特点1.2.1 特点11.2.2 特点21.2.3 特点31.3 联合体的大小1

Python标准库datetime模块日期和时间数据类型解读

《Python标准库datetime模块日期和时间数据类型解读》文章介绍Python中datetime模块的date、time、datetime类,用于处理日期、时间及日期时间结合体,通过属性获取时间... 目录Datetime常用类日期date类型使用时间 time 类型使用日期和时间的结合体–日期时间(

shell脚本批量导出redis key-value方式

《shell脚本批量导出rediskey-value方式》为避免keys全量扫描导致Redis卡顿,可先通过dump.rdb备份文件在本地恢复,再使用scan命令渐进导出key-value,通过CN... 目录1 背景2 详细步骤2.1 本地docker启动Redis2.2 shell批量导出脚本3 附录总

C语言中%zu的用法解读

《C语言中%zu的用法解读》size_t是无符号整数类型,用于表示对象大小或内存操作结果,%zu是C99标准中专为size_t设计的printf占位符,避免因类型不匹配导致错误,使用%u或%d可能引发... 目录size_t 类型与 %zu 占位符%zu 的用途替代占位符的风险兼容性说明其他相关占位符验证示

Linux系统之lvcreate命令使用解读

《Linux系统之lvcreate命令使用解读》lvcreate是LVM中创建逻辑卷的核心命令,支持线性、条带化、RAID、镜像、快照、瘦池和缓存池等多种类型,实现灵活存储资源管理,需注意空间分配、R... 目录lvcreate命令详解一、命令概述二、语法格式三、核心功能四、选项详解五、使用示例1. 创建逻

JAVA覆盖和重写的区别及说明

《JAVA覆盖和重写的区别及说明》非静态方法的覆盖即重写,具有多态性;静态方法无法被覆盖,但可被重写(仅通过类名调用),二者区别在于绑定时机与引用类型关联性... 目录Java覆盖和重写的区别经常听到两种话认真读完上面两份代码JAVA覆盖和重写的区别经常听到两种话1.覆盖=重写。2.静态方法可andro