关于 Spring SpEL 表达式
·
SpEL(Spring Expression Language) 是 Spring 提供的一套强大的表达式语言,类似于 OGNL、MVEL 或 EL,但功能更强大,能够在 运行时解析和执行表达式。
在 Spring 体系中,SpEL 常用于 配置、注解、条件判断、动态值计算 等场景。
一、什么是 SpEL

SpEL(Spring Expression Language) 是 Spring Core 提供的一种表达式解析框架,可以:
- 访问对象属性
- 调用方法
- 进行逻辑判断
- 操作集合
- 条件表达式
- Bean 引用
- 动态计算
典型使用场景:
| 场景 | 示例 |
|---|---|
@Value 动态配置 |
@Value("#{systemProperties['user.home']}") |
@Cacheable 条件 |
condition = "#user.id > 100" |
@PreAuthorize 权限 |
hasRole('ADMIN') |
| Spring XML | <property value="#{bean.name}" /> |
二、SpEL 架构原理
SpEL 解析流程:
执行过程:
- 解析表达式
- 构建 AST
- 创建上下文
- 执行表达式
- 返回结果
三、SpEL 基础用法
1 创建解析器
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello SpEL'");
String value = exp.getValue(String.class);
System.out.println(value);
输出:
Hello SpEL
2 访问对象属性
class User {
public String name = "Alice";
}
ExpressionParser parser = new SpelExpressionParser();
User user = new User();
StandardEvaluationContext context = new StandardEvaluationContext(user);
String name = parser.parseExpression("name").getValue(context, String.class);
System.out.println(name);
输出:
Alice
3 方法调用
ExpressionParser parser = new SpelExpressionParser();
String result = parser
.parseExpression("'spring'.toUpperCase()")
.getValue(String.class);
System.out.println(result);
输出:
SPRING
四、SpEL 运算符
SpEL 支持完整的运算符体系。
1 算术运算
parser.parseExpression("10 + 5").getValue();
parser.parseExpression("10 * 5").getValue();
parser.parseExpression("10 / 2").getValue();
支持:
+ - * / % ^
2 逻辑运算
parser.parseExpression("true and false").getValue();
parser.parseExpression("true or false").getValue();
parser.parseExpression("!true").getValue();
支持:
and
or
not
3 比较运算
parser.parseExpression("10 > 5").getValue();
parser.parseExpression("10 == 10").getValue();
parser.parseExpression("10 < 5").getValue();
支持:
> < >= <= == !=
五、访问集合
SpEL 对集合支持非常强。
1 List
List<String> list = List.of("A","B","C");
StandardEvaluationContext context =
new StandardEvaluationContext();
context.setVariable("list", list);
parser.parseExpression("#list[1]").getValue(context);
结果:
B
2 Map
Map<String,String> map = Map.of("name","Alice");
context.setVariable("map", map);
parser.parseExpression("#map['name']").getValue(context);
六、条件表达式
SpEL 支持类似 Java 的三元表达式。
parser.parseExpression("10 > 5 ? 'yes' : 'no'").getValue();
结果:
yes
七、对象创建
SpEL 可以动态创建对象。
parser.parseExpression("new java.util.Date()").getValue();
八、Bean 引用
在 Spring 容器中可以引用 Bean。
@Value("#{userService.userCount}")
private int userCount;
流程:
九、SpEL 在 Spring 注解中的应用
1 @Value
@Value("#{2 * 3}")
private int number;
2 @Cacheable
@Cacheable(
value = "user",
key = "#user.id",
condition = "#user.id > 100"
)
public User getUser(User user){
return user;
}
3 Spring Security
@PreAuthorize("#user.id == authentication.principal.id")
十、SpEL 高级特性
1 安全访问
parser.parseExpression("user?.name");
避免 NPE。
2 集合过滤
#users.?[age > 18]
含义:
过滤 age > 18 的元素
3 集合投影
#users.![name]
效果:
提取所有 name 字段
十一、SpEL 编译优化(性能)
SpEL 在 Spring 4.1+ 支持表达式编译。
SpelParserConfiguration config =
new SpelParserConfiguration(
SpelCompilerMode.IMMEDIATE,
this.getClass().getClassLoader());
ExpressionParser parser =
new SpelExpressionParser(config);
执行流程:
性能可提升 10x 以上。
十二、企业级使用建议
1 控制复杂度
避免:
@Cacheable(key="#user.orders[0].items[0].price * taxRate")
建议:
提前计算变量
2 防止安全风险
SpEL 可执行:
new java.lang.Runtime()
必须避免用户输入直接执行 SpEL。
3 高性能场景避免频繁解析
推荐:
缓存 Expression 对象
示例:
Expression exp = parser.parseExpression("user.name");
exp.getValue(context);
十三、SpEL vs 其他表达式语言
| 表达式语言 | 框架 | 特点 |
|---|---|---|
| SpEL | Spring | 与 Spring 深度集成 |
| OGNL | Struts | 早期流行 |
| MVEL | Drools | 高性能 |
| JEXL | Apache | 轻量 |
SpEL 优势
- Spring 原生支持
- 强大的集合操作
- 编译优化
- Bean 访问能力
总结
SpEL 是 Spring 体系中 非常核心但经常被低估的能力:
核心能力:
对象访问
方法调用
集合操作
条件表达式
Bean引用
动态计算
企业常见使用场景:
@Value@Cacheable@Scheduled@PreAuthorize- Spring XML 配置
✅ 一句话总结
SpEL 是 Spring 的“运行时 DSL”,让配置具备编程能力。
更多推荐

所有评论(0)