news 2026/4/23 20:27:27

@Value(Spring)的全面讲解 — 让你真会用它

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
@Value(Spring)的全面讲解 — 让你真会用它

@ValueSpring提供的注解(org.springframework.beans.factory.annotation.Value),用来把外部的配置值或 SpEL(Spring Expression Language)表达式注入到 Spring 管理的 bean 中。简单、灵活,适合注入单个值。但也有坑和替代方案(比如@ConfigurationProperties)。下面把常见用法、机制、技巧、陷阱与最佳实践都讲清楚,附带实战例子。


1. 最基础用法 — 注入配置属性

假设application.properties有:

app.name=MyApp app.timeout=5000

注入到字段:

@Component public class AppInfo { @Value("${app.name}") private String name; @Value("${app.timeout}") private int timeout; }
  • ${...}是占位符(property placeholder),会从 Spring 的Environment/PropertySources中解析(Spring Boot 自动加载application.properties/application.yml)。
  • 支持类型转换(String -> int)。

2. 提供默认值(非常常用)

如果配置不存在可以设置默认值,语法:${key:default}

@Value("${app.threadPoolSize:10}") private int poolSize; // 若没有配置,使用 10

3. SpEL(表达式)注入:#{...}

@Value也可以接受 SpEL 表达式(#{...}),可以执行方法、访问 bean、调用静态方法等:

@Value("#{T(java.lang.Math).random() * 100.0}") private double randomScore; @Value("#{anotherBean.someProperty}") private String fromOtherBean;

你也可以混用:在 SpEL 内部使用 property 占位符

@Value("#{T(java.lang.Integer).parseInt('${app.timeout:5000}')}") private int timeout;

4. 列表、数组、Map 注入(常见场景)

简单逗号分隔字符串转列表/数组

app.servers=10.0.0.1,10.0.0.2,10.0.0.3
@Value("#{'${app.servers}'.split(',')}") private List<String> servers;

Map 注入(复杂点)

可以使用 SpEL 把字符串解析为 map,但写法比较特殊:

my.map={key1:'v1', key2:'v2'}
@Value("#{${my.map}}") private Map<String, String> map;

注意:这种写法要求属性值符合 SpEL map 字面量语法。通常如果配置项很多或结构复杂,优先使用@ConfigurationProperties(更清晰、更可维护)。


5. 在构造器/方法参数上使用

@Component public class MyService { private final String name; public MyService(@Value("${app.name}") String name) { this.name = name; } }

Spring 支持给构造器或方法参数加@Value。在 Lombok 的@RequiredArgsConstructor场景下,通常使用@Value在构造器参数上不是很常见——更推荐把常量/配置放到@ConfigurationProperties后注入配置 bean。


6. 什么时候不要用@Value(以及替代)

  • 当你有很多相关配置(比如app.cache.*datasource.*)时,优先使用@ConfigurationProperties(prefix="..."),因为它能把一组配置映射成类型化 POJO,可验证(JSR-303)、更容易测试。
  • @Value适合:单个值、简单表达式、少量配置。

7. 注入静态字段?(不能直接)

@Value无法直接注入static字段(Spring 对实例字段注入)。常见做法:

@Component public class ConfigHolder { @Value("${app.name}") private String name; private static String APP_NAME; @PostConstruct public void init() { APP_NAME = name; // 把实例值传给静态变量 } public static String getAppName() { return APP_NAME; } }

但尽量避免静态注入,设计上不太优雅。


8. 注入顺序、解析器与实现细节(高级)

  • ${...}占位符的解析由 Spring 的占位符解析器处理(PropertySourcesPlaceholderConfigurer等)。在 Spring Boot 中,这些已经自动配置好了。
  • #{...}的 SpEL 表达式由 Spring 的ExpressionParser执行。
  • 你可以把${...}放在#{...}里面,两者可以互相嵌套(先解析占位符,或由 Spring 管理解析顺序),但要注意复杂嵌套可能增加可读性负担。
  • @Value的处理是 bean 初始化阶段完成的(在BeanPostProcessor的处理流程里),所以在@PostConstruct时字段已经注入完毕。

9. 常见错误与陷阱

  • NPE / 无法解析占位符:如果配置不存在且没有默认值,会抛异常(IllegalArgumentException),除非你允许占位符未解析(不常用)。解决:提供默认值或确保配置存在。
  • 类型转换失败:注入到intlongDuration等类型时,如果字符串格式不对会抛异常。Spring 能做常见类型转换,但复杂类型要小心。
  • Emoji / 特殊字符:在 properties/yml 中写特殊字符时要注意编码(UTF-8)。
  • 不可路由/不可变的集合:通过split得到的 List 是普通ArrayList,但如果直接尝试注入到不可变集合可能需要额外处理。
  • 测试场景:单元测试时要确保@Value所需的属性在 test 的Environment中可见(使用@TestPropertySource@SpringBootTest(properties = {...}))。

10. 示例汇总(一个实战类)

@Component public class ExampleConfig { @Value("${app.name:DefaultApp}") private String appName; @Value("${app.maxRetries:3}") private int maxRetries; @Value("#{'${app.servers:127.0.0.1}'.split(',')}") private List<String> servers; @Value("#{T(java.lang.Math).max(5, ${app.minValue:2})}") private int computed; // constructor injection example public ExampleConfig(@Value("${app.name}") String name) { System.out.println("constructed with name = " + name); } @PostConstruct public void init() { System.out.println(appName + "," + maxRetries + "," + servers + "," + computed); } }

11. 小结 / 建议清单(速记)

  • @Value("${key}")注入单个配置值或简单表达式。
  • ${key:default}提供默认值,避免解析失败。
  • 想做复杂的配置绑定(多个属性、嵌套结构),用@ConfigurationProperties
  • 需要引用 bean 属性或计算值时,用#{...}(SpEL)。
  • 不要把@Value用于大量配置,测试时确保属性可见。
  • 对于集合(List/Map),可用split或 SpEL map 字面量,但更复杂的话用@ConfigurationProperties
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 0:10:55

APEX实战第5篇:利用APEX程序直观体验向量近似检索能力

主流的数据模型 —— 从 JSON、XML、时序、空间&#xff0c;到图数据、区块链&#xff0c;再到如今最火的向量数据与 AI。利用 Oracle APEX&#xff0c;可以更简单、高效地展示数据库的多模能力。本文将通过一个 简明示例&#xff0c;演示如何使用 APEX 程序 直观地体验向量近似…

作者头像 李华
网站建设 2026/4/23 11:27:32

Powershell 入门(一)

Powershell 入门在 PowerShell 中标识和修改执行策略PowerShell 中的执行策略旨在最大程度地减少用户无意中运行 PowerShell 脚本的可能性。 你可以将其视为一项安全功能&#xff0c;用于控制 PowerShell 加载配置文件和运行脚本的条件。 此功能有助于防止恶意脚本的执行。若要…

作者头像 李华
网站建设 2026/4/23 11:29:16

无锡黑锋 HF3613 40V热插拔、50V耐压、固定限流保护开关技术解析

一、芯片核心定位HF3613 是一款采用 SOT23-3 经典封装、集成固定阈值保护的 高压前端保护开关IC 其核心价值在于 高达50V的输入瞬态耐压、40V的热插拔耐受能力 以及 内置的 2.0A 固定过流保护 专为 智能手机、平板电脑、便携媒体设备 等对成本与PCB面积有严格要求的充电输入端口…

作者头像 李华
网站建设 2026/4/23 11:29:46

基于Spring Boot + Vue的租车网站系统

基于Spring Boot Vue的租车网站系统介绍 一、系统背景与目标 传统租车行业依赖线下门店和人工操作&#xff0c;存在信息不透明、流程繁琐、用户体验差等问题。本系统基于Spring Boot&#xff08;后端&#xff09;与Vue.js&#xff08;前端&#xff09;技术栈开发&#xff0c;旨…

作者头像 李华
网站建设 2026/4/23 11:27:31

】setTimeout 延时为 0 的情况

基础问答问题&#xff1a;你在写代码的过程中&#xff0c;在什么时候才会设置 setTimeout 的延时为 0&#xff1f;回答&#xff1a;有如下几种情况避免同步任务阻塞 UI&#xff0c;即在渲染较多数据的时候&#xff0c;可以通过 setTimeout 分批渲染。const data new Array(100…

作者头像 李华
网站建设 2026/4/23 13:11:36

.NET开发中3秒判断该用 IEnumerable 还是 IQueryable

选择 IEnumerable 当&#xff1a;1、数据已在内存中// 数据来自内存集合List<User> users GetUsersFromMemory();var result users.Where(u > u.Age > 18); // 使用 IEnumerable2、需要立即执行查询var users dbContext.Users.ToList() // 立即执行.Where(u >…

作者头像 李华