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()} 最灵活 💪

相关推荐
神明9315 分钟前
数据库模型设计实战:如何导出数据库完整数据字典_规范化流程
jvm·数据库·python
老纪7 分钟前
SQL中如何查找包含关键字的行:FULLTEXT全文索引检索
jvm·数据库·python
茉莉玫瑰花茶8 分钟前
LangGraph 入门教程:构建 AI 工作流 [ 案例二 ]
开发语言·人工智能·python
yaoxin5211238 分钟前
403. Java 文件操作基础 - 写入二进制文件
java·开发语言·python
dfdfadffa9 分钟前
c++怎么利用std--filesystem--path处理包含多个扩展名的文件名【详解】
jvm·数据库·python
Java面试题总结16 分钟前
spring重点详解
java·后端·spring
阿正呀21 分钟前
c++如何动态追加JSON数组到已有文件_nlohmann局部修改【详解】
jvm·数据库·python
m0_6908258222 分钟前
CSS如何使用-disabled控制禁用按钮的鼠标样式_通过状态伪类优化交互
jvm·数据库·python
财经资讯数据_灵砚智能23 分钟前
基于全球经济类多源新闻的NLP情感分析与数据可视化(日间)2026年5月11日
大数据·人工智能·python·信息可视化·自然语言处理
2301_7950997424 分钟前
JavaScript事件委托机制在高性能列表开发中的应用
jvm·数据库·python