Spring Expression Language (SpEL) Overview and Practical Usage
This article introduces Spring Expression Language (SpEL), explains its common syntax, demonstrates quick-start examples, shows real-world usage with AOP monitoring, and outlines its internal implementation, providing a concise guide for backend developers working with Spring.
Introduction
Spring Expression Language (SpEL) is a powerful expression language that supports runtime querying and manipulation of object graphs. It is part of Spring's core container alongside Beans, Core, and Context modules, and can be used with XML or annotation‑based configurations.
Common SpEL Usage
SpEL syntax resembles JSP EL and uses #{…} as delimiters. Supported expressions include literals (integers, decimals, scientific notation, strings, booleans), bean/property/method references, static method/field access, and various operators (arithmetic, comparison, logical, ternary, Elvis, regular expressions).
Quick Start
Simple examples demonstrate how to evaluate literal strings, invoke methods, and work with object properties using SpelExpressionParser and Expression objects.
public void demo() {
// 1 Define parser
SpelExpressionParser parser = new SpelExpressionParser();
// 2 Parse expression
Expression exp = parser.parseExpression("'xxx'");
// 3 Get result
String value = (String) exp.getValue();
System.out.println(value); // xxx
} public void demo() {
// 1 Define parser
SpelExpressionParser parser = new SpelExpressionParser();
// 2 Parse expression
Expression exp = parser.parseExpression("'xxx'.concat('yyy')");
String value = (String) exp.getValue();
System.out.println(value); // xxxyyy
exp = parser.parseExpression("'xxx'.bytes");
byte[] bytes = (byte[]) exp.getValue();
exp = parser.parseExpression("'xxx'.bytes.length");
int length = (Integer) exp.getValue();
System.out.println("length: " + length); // length: 3
} public void demo() {
User user = new User();
user.setName("xxx");
User user2 = new User();
user2.setName(user.getName());
// 1 Define parser
ExpressionParser parser = new SpelExpressionParser();
// Specify expression
Expression exp = parser.parseExpression("name");
// 2 Get property value
String name = (String) exp.getValue(user2);
System.out.println(name); // xxx
// 2.1 Evaluate expression
Expression exp2 = parser.parseExpression("name == 'xxx'");
boolean result = exp2.getValue(user2, Boolean.class);
System.out.println(result); // true
}Real‑world Application
In practice, SpEL is often used to evaluate object properties within AOP‑based monitoring. An example shows a custom @Monitor annotation that captures method parameters via SpEL, builds a monitoring key, and asynchronously sends alert information.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Monitor {
MonitorScenesTypeEnum scenes() default MonitorScenesTypeEnum.DEFAULT;
String monitorSpEL() default "";
} public void process(Monitor monitor, JoinPoint joinPoint, Object result, Throwable ex) throws ClassNotFoundException {
MonitorScenesTypeEnum scenes = monitor.scenes();
Integer code = scenes.getCode();
// Get Apollo config
Map
monitorConfigMap = apolloConfigService.getMonitorConfigMap();
if (MapUtils.isEmpty(monitorConfigMap) || !monitorConfigMap.containsKey(code)) {
return;
}
MonitorConfig monitorConfig = monitorConfigMap.get(code);
// Validate result if needed
String resultType = monitorConfig.getResultType();
if (checkResult(result, resultType)) {
return;
}
// Parse SpEL expression from annotation
String monitorSpEL = monitor.monitorSpEL();
String monitorTrace = StringUtils.isNotBlank(monitorSpEL) ?
SpelParseUtil.generateKeyBySpEL(monitorSpEL, joinPoint) : StringUtils.EMPTY_STRING;
// Capture exception info
String otherParamsJson = "";
if (Objects.nonNull(ex)) {
Map
otherParams = Maps.newHashMap();
String stackTraceAsString = Throwables.getStackTraceAsString(ex);
String errMsg = stackTraceAsString;
if (stackTraceAsString.length() > NumberConstant.NUMBER_512) {
errMsg = stackTraceAsString.substring(0, NumberConstant.NUMBER_512) + "...";
}
otherParams.put("异常信息", errMsg);
otherParamsJson = JsonUtil.silentObject2String(otherParams);
}
// Asynchronously send alert
asyncSendMonitor(scenes, monitorTrace, otherParamsJson);
} private static SpelExpressionParser parser = new SpelExpressionParser();
private static DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
public static String generateKeyBySpEL(String spelString, JoinPoint joinPoint) {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
String[] paramNames = nameDiscoverer.getParameterNames(method);
Expression expression = parser.parseExpression(spelString);
EvaluationContext context = new StandardEvaluationContext();
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
context.setVariable(paramNames[i], args[i]);
}
return Objects.requireNonNull(expression.getValue(context)).toString();
} @Monitor(scenes = MonitorScenesTypeEnum.CHANGE_PRICE_FAIL, spelStr = "#request?.orderId")
public ChangePriceResponse changePrice(ChangePriceRequest request) {
BizOrderContext
bizOrderContext =
BizOrderContext.create(OrderEventEnum.C1_CHANGE_JM_PRICE, request);
ZzAssert.isTrue(stateMachine.isCanFire(bizOrderContext), BizErrorCode.ORDER_STATUS_CHANGED);
stateMachine.fire(bizOrderContext);
return bizOrderContext.getResponse();
}Simple Overview of SpEL Internal Implementation
SpEL parsing starts with ExpressionParser#parseExpression , which performs lexical analysis to split the expression into tokens, builds an abstract syntax tree (AST) using SpelNode , wraps it into an Expression , and later evaluates it against an EvaluationContext when Expression#getValue is called.
Conclusion
SpEL is widely used in Spring applications for dynamic expression evaluation, including monitoring, dynamic index creation, lock handling, caching, and within annotations such as @Cacheable , @Value , and Spring Security's @PreAuthorize family.
Zhuanzhuan Tech
A platform for Zhuanzhuan R&D and industry peers to learn and exchange technology, regularly sharing frontline experience and cutting‑edge topics. We welcome practical discussions and sharing; contact waterystone with any questions.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.