Mastering Spring SpEL: From Basics to Real-World AOP Integration
An in‑depth guide to Spring Expression Language (SpEL) covering its core features, evaluation contexts, parser configuration, collection handling, operators, variables, bean references, and a practical AOP case study, all illustrated with concise Java code examples.
Environment: Spring 5.3.23
1. Introduction
Spring Expression Language (SpEL) is a powerful expression language that can query and manipulate object graphs at runtime. Its syntax resembles Unified EL but adds features such as method invocation and basic string templating.
Although other Java expression languages exist (Avaitor, OGNL, MVEL, JBoss EL), SpEL was created to provide a well‑supported language for the Spring ecosystem and can be used independently of Spring.
Supported features
Literal expressions
Boolean and relational operators
Regular expressions
Class expressions
Access to properties, arrays, lists and maps
Method invocation
Relational operators
Constructor invocation
Bean references
Array construction
Inline lists
Template expressions
The article focuses on the most commonly used features and ends with a practical case study.
2. Evaluation Context
EvaluationContext is the interface used to evaluate expressions, resolve properties, methods, or fields, and perform type conversion. Spring provides two implementations:
SimpleEvaluationContext : a restricted subset of SpEL suitable for read‑only or limited use cases.
StandardEvaluationContext : full access to all SpEL features and configurable root object.
SimpleEvaluationContext can be built with a fluent builder to enable read‑only data binding, read‑write data binding, or custom PropertyAccessor only.
<code>static class Person {
String name = "张三";
}
SimpleEvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
ExpressionParser parser = new SpelExpressionParser();
Person root = new Person();
parser.parseExpression("name").setValue(context, root, "李四"); // throws because context is read‑only
</code>3. SpelParserConfiguration
The SpelParserConfiguration object customises the parser behaviour, e.g., automatic creation of collection elements when an out‑of‑range index is accessed.
<code>class Person {
public List<String> list;
}
SpelParserConfiguration config = new SpelParserConfiguration(true, true);
ExpressionParser parser = new SpelExpressionParser(config);
Expression exp = parser.parseExpression("list[3]");
Person root = new Person();
System.out.println(exp.getValue(rootObject)); // prints null
System.out.println(rootObject.list.size() + ", " + rootObject.list); // prints 4, [ , , , ]
</code>4. Expression Definition
SpEL expressions can be embedded in XML or annotation metadata using the syntax #{<expression>} . Example:
<code><bean id="order" class="com.pack.Order">
<property name="totalAmount" value="#{ T(java.lang.Math).random() * 1000.0 }"/>
</bean>
</code>4.1 Collection Access and Creation
Examples of accessing lists, maps, arrays and creating collections directly from expressions.
<code>// List access
String name = parser.parseExpression("persons[0].name").getValue(context, String.class);
// Map access
String name = parser.parseExpression("mappings['p2'].name").getValue(context, String.class);
// Array access
String name = parser.parseExpression("ps[1].name").getValue(context, String.class);
// List creation
List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue(context);
// Map creation
Map person = (Map) parser.parseExpression("{name:'张三', age:'23'}").getValue(context);
</code>4.2 Method Invocation
<code>StandardEvaluationContext context = new StandardEvaluationContext();
context.setRootObject(new Person("莉莉"));
ExpressionParser parser = new SpelExpressionParser();
String value = parser.parseExpression("getName()").getValue(context, String.class);
</code>4.3 Operators
Relational, logical and arithmetic operators are supported.
<code>boolean ret = parser.parseExpression("2 == 2").getValue(Boolean.class); // true
ret = parser.parseExpression("2 < -5.0").getValue(Boolean.class); // false
ret = parser.parseExpression("'black' < 'block'").getValue(Boolean.class); // true
</code>4.4 Variables
Variables can be set in the context and referenced with #variableName . The special variables #this and #root refer to the current evaluation object and the root object respectively.
<code>StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("address", "新疆乌鲁木齐");
String address = parser.parseExpression("#address").getValue(context, String.class);
</code>4.5 Custom Methods and Bean References
<code>static class NameUtils {
public static String reverseString(String input) { /* ... */ }
}
context.setVariable("reverseString", NameUtils.class.getDeclaredMethod("reverseString", String.class));
String ret = parser.parseExpression("#reverseString('pack')").getValue(context, String.class);
</code>When a bean resolver is configured, beans can be accessed with the @beanName syntax.
5. Real‑World Case: Using SpEL in AOP
An annotation @AuthorityAuthentication carries a SpEL expression for the id attribute. The aspect extracts method arguments, populates the evaluation context, evaluates the expression, and logs the operation.
<code>@Aspect
static class LogAspect {
@Before("execution(* com.pack.main.aspect..*.*(..)) && @annotation(authority)")
public void beforeSpel(JoinPoint point, AuthorityAuthentication authority) {
// populate context with method arguments
// evaluate authority.id() expression
}
}
</code>Service method example:
<code>@AuthorityAuthentication(value="ps:teacher:update", id="#teacher.id")
public void operator(Teacher teacher) { /* ... */ }
</code>Running the test prints:
<code>权限标识: ps:teacher:update, SpEL: #teacher.id
记录Teacher【666】日志...
教师修改成功...
</code>Summary: In Spring SpEL, “Evaluation” refers to the process of evaluating an expression to obtain a result. SpEL provides a concise and powerful way to query and manipulate objects.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
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.