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 解析流程:

SpEL Expression

ExpressionParser

AST 抽象语法树

EvaluationContext

Expression Evaluation

Result

执行过程:

  1. 解析表达式
  2. 构建 AST
  3. 创建上下文
  4. 执行表达式
  5. 返回结果

三、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;

流程:

SpringContainer SpEL Bean SpringContainer SpEL Bean 解析表达式 获取Bean 返回Bean 计算结果

九、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);

执行流程:

Yes

Expression

Parse AST

Interpret Execution

Hotspot

Compile to Bytecode

Faster Execution

性能可提升 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”,让配置具备编程能力。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐