Spring的SPEL(Spring Expression Language)的使用说明,包含语法、示例和常见场景
以下是Spring的SPEL(Spring Expression Language)的使用说明,包含语法、示例和常见场景:
1. 基本语法
变量引用
- 表达式:
#{变量名}
(如#{systemProperties['os.name']}
) - 作用域:在Spring配置中使用
@Value
或@SpEL
注解。
类型引用(T())
- 语法:
T(类全限定名)
- 示例:
// 获取静态常量 #{T(java.lang.Math).PI} → 3.141592653589793 // 调用静态方法 #{T(java.util.Arrays).asList(1,2,3)}
Bean引用(@)
- 语法:
@beanName
- 示例:
// 获取名为"myService"的Bean #{@myService.someMethod()}
属性访问
- 语法:
对象.属性
或对象[索引/键]
- 示例:
// 访问对象属性 #{user.name} // 访问数组元素 #{numbers[0]}
运算符
- 算术运算:
+ - * / %
- 比较运算:
== != > < >= <=
- 逻辑运算:
and or not
- 三元运算:
条件 ? trueValue : falseValue
2. 常见使用场景
场景1:动态注入值
@Component
public class MyBean {
@Value("#{systemProperties['user.home']}")
private String userHome; // 获取系统属性"用户目录"
}
场景2:条件判断
<!-- 在XML中根据条件注入 -->
<bean id="dataSource" class="com.example.DataSource"
p:driver="#{ systemProperties['env'] == 'prod' ? 'com.mysql.jdbc.Driver' : 'org.h2.Driver' }"/>
场景3:调用Bean方法
@Value("#{ @myService.generateId() }")
private String dynamicId; // 调用myService的generateId()方法
场景4:集合操作
@Value("#{ { 'a', 'b', 'c' } }")
private List<String> list; // 直接创建集合
@Value("#{ T(java.util.Arrays).asList(1,2,3).stream().map(it -> it*2).collect(Collectors.toList()) }")
private List<Integer> doubledList; // 使用流操作
3. 进阶用法
安全导航操作符(?.)
- 作用:避免空指针异常
- 示例:
#{user?.address?.city} // 若user或address为空,返回null而非抛异常
正则表达式匹配
@Value("#{ 'abc123' matches '^\\d+$' }")
private boolean isNumeric; // 返回false
集合投影和筛选
@Value("#{ customers.?[age > 18] }")
private List<Customer> adults; // 筛选年龄>18的客户
@Value("#{ customers.![name] }")
private List<String> names; // 提取所有客户的name属性
4. 代码示例
示例1:在XML中使用SPEL
<bean id="configBean" class="com.example.Config">
<property name="dynamicValue" value="#{ 'Hello ' + T(java.time.LocalDateTime).now() }"/>
</bean>
示例2:在Java配置中使用
@Configuration
public class AppConfig {
@Bean
public MyBean myBean() {
MyBean bean = new MyBean();
bean.setUrl("#{ @environment.getProperty('app.baseUrl') }"); // 调用Bean方法
return bean;
}
}
5. 常见问题
Q1:表达式解析失败
- 原因:变量未注册、语法错误、作用域问题
- 解决:
// 确保在SpEL上下文中注册变量 ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); context.setVariable("user", new User()); parser.parseExpression("#user.name").getValue(context); // 成功
Q2:调用Bean方法失败
- 原因:Bean未被Spring管理或方法未正确注入
- 解决:
@Component public class MyService { public String generateId() { return UUID.randomUUID().toString(); } } // 在SPEL中直接调用 #{ @myService.generateId() }
6. 对比表格
功能 | 语法示例 | 适用场景 |
---|---|---|
系统属性 | #{systemProperties['os.name']} | 动态获取系统属性 |
静态方法调用 | T(java.util.UUID).randomUUID() | 使用静态方法生成唯一ID |
条件判断 | #{ env == 'prod' ? 'MySQL' : 'H2' } | 根据环境配置不同值 |
调用Bean方法 | #{@myService.someMethod()} | 动态获取Bean的返回值 |
集合操作 | #{ customers.?[age > 18] } | 过滤或转换集合元素 |
总结
Spring SPEL是强大的表达式语言,适用于:
- 动态配置:根据环境或运行时数据调整配置。
- 复杂逻辑:在配置中嵌入条件判断、集合操作。
- 方法调用:直接调用Bean的方法或静态方法。
- 安全操作:通过
?.
避免空指针异常。
通过结合注解(如@Value
)和XML配置,可以灵活地在Spring应用中使用SPEL实现动态行为。