${} 与 #{} 的核心区别
| 特性 | ${} |
#{} |
|---|---|---|
| 名称 | 属性占位符 | 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()}最灵活 💪