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

相关推荐
LOVE️YOU2 小时前
Python 中 Tuple 为什么有时可 Hash,有时不可 Hash?
开发语言·python·哈希算法
小oo呆2 小时前
【学习心得】迭代器和可迭代对象
开发语言·python
AC赳赳老秦2 小时前
采集行为合规自检:OpenClaw 自动校验 robots 协议与采集频率,规避违规采集风险
java·开发语言·c++·python·php·deepseek·openclaw
迅猛龙办公室2 小时前
Python输出当前计算机的系统日期和时间
开发语言·前端·python
XiaoMaqqqq4 小时前
知名的IP驱动产业新场景新工具
网络·python·网络协议·tcp/ip
言乐64 小时前
Python实现语音审核模型
开发语言·python·django·virtualenv·pygame
ITHAOGE154 小时前
下载 | Win10 2021纯净精简版,预装应用极少!(9月更新、Win10 IoT LTSC 2021版、适合老电脑)
windows·科技·物联网·微软·电脑
步行cgn4 小时前
Spring 全注解开发详解
java·后端·spring
程序员清风5 小时前
Python 数据分析环境搭建:从 Jupyter 到 pandas
python·jupyter·数据分析
月光船幽幽5 小时前
加性偏移外推提升参数识别可靠性
python·算法