当前位置: 首页 > java >正文

Spring **${}** vs **#{}** 语法全景图

Spring ${} vs #{} 语法全景图

一句话记忆:
${}占位符(静态字符串替换),#{}SpEL 表达式(运行时计算)。
二者可以 嵌套联动,带来 声明式动态能力


一、基础区别

维度${}#{}
名称Property PlaceholderSpEL(Spring Expression Language)
求值时机容器启动时 替换运行时 解析
数据来源Environment、PropertySourceBean、系统属性、运算、方法调用
常见用途读取 application.yml计算、条件、集合、Bean 调用
示例${server.port}#{T(java.lang.Math).random()}
默认值${key:default}#{key ?: default}

二、基础用法对比

1️⃣ 读取配置

my:name: Tomage: 18
@Value("${my.name}")           // Tom
private String name;@Value("${my.age}")            // 18(字符串)
private int age;@Value("${unknown:default}")   // default
private String fallback;

2️⃣ 运行时计算

@Value("#{T(java.lang.Math).random() * 100}")
private double rand100;@Value("#{systemProperties['os.name']}")
private String os;

三、混合嵌套(经典技巧)

@Value("#{${feature.price} * (1 + ${feature.tax})}")
private BigDecimal finalPrice;
  • ${feature.price} 先被替换为 100,表达式变为 #{100 * (1 + 0.2)}120

四、高级用法速查表

场景代码示例
三目/Elvis"#{flag ? 'A' : 'B'}" / "#{name ?: 'NO_NAME'}"
集合索引"${list[0]}" / "#{map['key']}"
集合过滤 & 投影"#{users.?[age > 18].![name]}"
正则匹配"#{email matches '^[\\w\\.-]+@(.+)$'}"
Bean 调用"#{priceService.current() * 1.1}"
静态方法"#{T(java.time.LocalDate).now()}"
条件 Bean 注册@ConditionalOnExpression("#{env['spring.profiles.active'] == 'prod'}")

五、XML / 注解 / 编程式 全场景

场景写法
XML<property name="timeout" value="#{${timeout} * 1000}"/>
@Bean@Bean @ConditionalOnExpression("#{systemProperties['debug'] != null}")
编程式ExpressionParser parser = new SpelExpressionParser();

六、常见误区 & 避坑

说明
${} 不支持运算${1+2} 会原样输出,不会被计算
#{}application.yml 无效只能在 @ValueXML@Conditional 等场景使用
构造器注入 无法实时刷新使用 @ConfigurationProperties 或字段注入
默认值写法${key:default} vs #{key ?: default}

七、一句话总结

${} 负责“占位”,#{} 负责“计算”;
二者嵌套即可实现声明式动态配置,让 Spring 在运行时依旧“活”起来。

http://www.xdnf.cn/news/16967.html

相关文章:

  • 【C++ 初级工程师面试--5】inline内联函数特点 、和普通函数的区别、什么时候适合内联?
  • Shell脚本-变量如何定义
  • 什么是DOM和BOM?
  • 搜索引擎评估革命:用户行为模型如何颠覆传统指标?
  • 数据结构1-概要、单向链表
  • [网安工具] Web 漏洞扫描工具 —— AWVS · 使用手册
  • 【C语言】内存函数与数据在内存中的存储
  • python -m build打包成为tar.gz或者whl
  • Qemu-NUC980(二):时钟clock代码添加
  • Redis数据库存储键值对的底层原理
  • SpringBoot相关注解
  • #Linux内存管理#缺页中断处理的核心函数是do_page_fault()的工作原理
  • Vulnhub ELECTRICAL靶机复现(附提权)
  • RPG增容2.尝试使用MMC根据游戏难度自定义更改怪物属性(三)
  • (LeetCode 面试经典 150 题) 138. 随机链表的复制 (哈希表)
  • Kotlin单例模式懒汉模式:LazyThreadSafetyMode.SYNCHRONIZED(2)
  • 深度学习(鱼书)day09--与学习相关的技巧(前三节)
  • P10816 [EC Final 2020] Namomo Subsequence|普及+
  • 机器学习实战:KNN算法全解析 - 从原理到创新应用
  • 【LeetCode 热题 100】(三)滑动窗口
  • Windows下定位Mingw编译的Qt程序崩溃堆栈
  • Python编程基础与实践:Python模块与包入门实践
  • 滚珠花键在汽车制造中有哪些高要求?
  • 什么叫湖仓一体
  • 存储过程的介绍、基本语法、delimiter的使用
  • Effective C++ 条款18:让接口容易被正确使用,不易被误用
  • Qwen3 Embedding:新一代文本表征与排序模型
  • [硬件电路-123]:模拟电路 - 信号处理电路 - 常见的高速运放芯片、典型电路、电路实施注意事项
  • 高效游戏状态管理:使用双模式位运算与数学运算
  • 网络基础实操篇-05-路由基础-最佳实践