spring #{} 与 ${} 区别

${}#{} 的核心区别

特性 ${} #{}
名称 属性占位符 SpEL表达式
解析时机 启动时/类加载时 运行时
执行引擎 Spring属性解析器 Spring表达式语言(SpEL)
主要用途 读取配置文件 执行表达式/方法调用
动态计算 静态值替换 动态计算
默认值 支持 ${key:default} 需要在内部使用${}

1. ${} - 属性占位符

功能:从Spring Environment、properties文件、YAML文件中读取配置值

java 复制代码
@Component
@RocketMQMessageListener(
    topic = "${rocketmq.topic}",           // 从配置文件读取
    consumerGroup = "${rocketmq.group:default-group}" // 带默认值
)

YAML配置:

bash 复制代码
rocketmq:
  topic: test-topic
  group: test-group

特点:

  • ✅ 只能做静态值替换

  • ✅ 支持默认值 ${key:default}

  • ✅ 不支持运算、方法调用

  • ✅ 解析发生在依赖注入阶段


2. #{} - SpEL表达式

功能:执行Java代码、调用方法、访问Bean属性、进行运算

java 复制代码
@Component
@RocketMQMessageListener(
    // 调用Bean的方法
    topic = "#{@topicConfig.getTopic()}",
    
    // 访问Bean属性
    consumerGroup = "#{@consumerProperties.group}",
    
    // 三目运算符
    selectorExpression = "#{@config.env == 'prod' ? 'tag1' : 'tag2'}"
)

支持的表达式:

java 复制代码
// 调用静态方法
#{T(System).currentTimeMillis()}

// 字符串操作
#{'${rocketmq.topic}'.toUpperCase()}

// 条件运算
#{@conditionService.isEnable() ? 'topicA' : 'topicB'}

// 数学运算
#{${server.port:8080} + 1}

3. 两者组合使用

java 复制代码
@Component
@RocketMQMessageListener(
    // ${} 作为 #{} 的参数
    topic = "#{'${rocketmq.topic:default}'.toUpperCase()}",
    
    // 读取配置并进行运算
    consumerGroup = "#{'group-' + '${rocketmq.group:default}'}",
    
    // 复杂逻辑
    selectorExpression = "#{@tagService.getTags('${rocketmq.biz.type}')}"
)

4. 典型应用场景对比

场景 推荐方式 示例
读取简单配置 ${} ${rocketmq.topic}
配置默认值 ${} ${rocketmq.group:default}
调用Bean方法 #{} #{@service.method()}
字符串处理 #{} #{'test'.toUpperCase()}
条件判断 #{} #{@env == 'dev' ? A : B}
访问数组/集合 #{} #{@config.list[0]}
配置文件转大写 ${} + #{} #{'${topic}'.toUpperCase()}

5. 注解中使用的限制

Spring注解中 (如@Value@RocketMQMessageListener):

  • ${} - 直接支持,自动解析配置文件

  • #{} - 需要配置spring.factories或特定版本才支持

java 复制代码
// ✅ 直接工作
@Value("${rocketmq.topic}")

// ⚠️ 部分注解不支持#{},或需要特殊处理
@RocketMQMessageListener(topic = "#{...}")  // 某些版本可能不解析

6. 最佳实践建议

简单场景:只用${}

java 复制代码
@RocketMQMessageListener(
    topic = "${rocketmq.topic}",
    consumerGroup = "${rocketmq.group}"
)

复杂场景:在#{}内嵌${}

java 复制代码
@RocketMQMessageListener(
    topic = "#{'${rocketmq.topic}'.trim()}",
    consumerGroup = "#{@environment.getProperty('rocketmq.group')}"
)

无法使用#{}时:通过中间Bean

java 复制代码
@Component
public class TopicProvider {
    @Value("${rocketmq.topic}")
    private String topic;
    
    public String getTopic() {
        return topic.toUpperCase(); // 复杂处理
    }
}

// 使用时
@RocketMQMessageListener(
    topic = "#{@topicProvider.getTopic()}"
)

总结

  • ${}:读配置,静态替换,简单直接 ✅

  • #{}:执行代码,动态计算,功能强大 ⚡

  • 组合使用#{'${key}'.method()} 最灵活 💪

相关推荐
shirsl2 小时前
算法 Day1-数组 / 哈希 + 双指针
python·算法·哈希算法
dadaobusi6 小时前
学习:RV lkvm SBI
java·学习·spring
广州山泉婚姻8 小时前
Python序列号源码分析
python
HEJOO98 小时前
深入理解 Java volatile 关键字:原理、用法与常见误区
java·开发语言·spring
计算机源码社8 小时前
【大数据项目实战】基于大数据的影视内容生态综合质量分析与可视化-基于数据挖掘的影视内容类型共现与口碑聚类分析系统
大数据·人工智能·python·数据挖掘·数据分析·毕业设计·课程设计
C^h8 小时前
pytorch 适合初学者 0基础学习
人工智能·pytorch·python
小柯南敲键盘9 小时前
跨马翻译:AI批量图片翻译工具,跨境电商视频字幕翻译与智能抠图一体搞定
人工智能·python·音视频
2601_962297259 小时前
Python里behave和pytest-bdd哪个更适合中大型项目?为什么?
python·bdd·行为驱动开发·behave·pytest-bdd
Wang's Blog10 小时前
Java框架快速入门: Spring Security+OAuth2之HTTP请求结构与认证基础
java·spring·http
YCOSA202511 小时前
系统工具使用检测.exe (仅供娱乐)
python·microsoft