java开发中#和$的区别
在Spring框架中,$
和 #
是两种不同的表达式前缀,用于从不同的来源获取值或执行计算。下面详细解释它们的区别和用法:
一、$
占位符(Property Placeholder)
1. 作用
- 从配置文件(如
application.properties
、application.yml
)、环境变量或系统属性中获取值。 - 语法:
${property.key}
2. 示例
@Value("${app.name}") // 从配置文件中获取值
private String appName; // 对应配置:app.name=MyApp@Value("${server.port:8080}") // 使用默认值(若配置不存在)
private int port; // 若server.port未定义,默认8080@Value("${JAVA_HOME}") // 获取系统环境变量
private String javaHome;
3. 配置文件示例
# application.properties
app.name=MyApp
server.port=8081
二、#
SpEL表达式(Spring Expression Language)
1. 作用
- 执行动态表达式计算,支持方法调用、属性访问、算术运算等。
- 可以引用其他Bean、系统属性或环境变量。
- 语法:
#{expression}
2. 示例
@Value("#{systemProperties['java.version']}") // 获取系统属性
private String javaVersion;@Value("#{new java.util.Date()}") // 创建新对象
private Date currentDate;@Value("#{mathService.pi * 2}") // 引用其他Bean的属性/方法
private double circleLength;@Value("#{environment.getProperty('app.name')}") // 获取环境变量
private String envAppName;@Value("#{'${app.name}'.toUpperCase()}") // 组合使用:先获取配置值,再转换为大写
private String upperCaseName;
三、核心区别对比
对比项 | ${...} | #{...} |
---|---|---|
名称 | 属性占位符(Property Placeholder) | SpEL表达式(Spring Expression Language) |
主要用途 | 从配置文件、环境变量获取值 | 执行动态表达式计算 |
支持计算 | 不支持(只能获取原始值) | 支持(如 #{1 + 2} , #{bean.method()} ) |
引用其他Bean | 不支持 | 支持(如 #{dataSource.url} ) |
默认值 | 支持(如 ${key:default} ) | 不直接支持(需用 ?: 操作符) |
四、常见组合用法
1. 在SpEL中引用配置值
@Value("#{'${app.name}'.toUpperCase()}") // 先获取配置值,再转为大写
private String upperCaseName;@Value("#{${app.timeout} * 2}") // 先获取配置值,再进行计算
private long doubleTimeout;
2. 复杂表达式
@Value("#{systemProperties['os.name'].contains('Windows') ? 'C:/temp' : '/tmp'}")
private String tempDir; // 根据操作系统动态选择临时目录
五、注意事项
-
语法错误:
@Value("${app.name")
缺少右括号,会导致解析错误。- 正确写法:
@Value("${app.name}")
或@Value("#{bean.property}")
-
转义字符:
- 若需要在值中包含
$
或#
,需使用\
转义:@Value("\\${literal.value}") // 注入字符串 "${literal.value}"
- 若需要在值中包含
-
生效时机:
${...}
在Bean创建时替换为实际值。#{...}
在表达式计算时动态求值。
总结
${...}
:用于从配置文件、环境变量中获取静态值。#{...}
:用于执行动态表达式计算,支持更复杂的逻辑。
在实际开发中,两者经常结合使用,例如先通过 ${...}
获取配置值,再通过 SpEL 进行加工处理。