SpEL的全称为 Spring Expression Language,具有再运行时构建复杂表达式、存取对象图属性、对象方法调用等功能
下面是一个简单样例
public class SpelTest {
@Test
public void test1() {
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = new StandardEvaluationContext();
Expression expression = parser.parseExpression("'Hello' + ' world' + '!'");
System.out.println(expression.getValue(context));
}
}
输出:
Hello world!
可以看到,再这个例子中,表达式为'Hello' + ' world' + '!'
,可以看作是'Hello'
,' world'
和'!'
三个字符串的拼接,解析后返回Hello world!
SpEL也支持数字运算:
@Test
public void test2() {
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = new StandardEvaluationContext();
Expression expression = parser.parseExpression("100 + 10");
System.out.println(expression.getValue(context));
expression = parser.parseExpression("100 - 10");
System.out.println(expression.getValue(context));
expression = parser.parseExpression("100 * 10");
System.out.println(expression.getValue(context));
expression = parser.parseExpression("100 / 10");
System.out.println(expression.getValue(context));
expression = parser.parseExpression("100 > 10");
System.out.println(expression.getValue(context));
expression = parser.parseExpression("100 > 10 ? 'A' : 'B'");
System.out.println(expression.getValue(context));
}
输出:
110
90
1000
10
true
A
此外,SpEL也可以解析方法调用,能够获取调用指定类的指定方法和属性:
@Test
public void test3() {
UserInfo userInfo = new UserInfo();
userInfo.setUserName("AAA");
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext(userInfo);
String getUserName = "getUserName";
Expression expression = parser.parseExpression(getUserName);
System.out.println(expression.getValue(context));
}
输出:
AAA
也可以设置参数:
@Test
public void test4() {
UserInfo userInfo = new UserInfo();
userInfo.setUserName("BBB");
ExpressionParser parser = new SpelExpressionParser();
String setUserName = "setUserName(#userName)";
StandardEvaluationContext context = new StandardEvaluationContext(userInfo);
context.setVariable("userName", "AAA");
Expression expression = parser.parseExpression(setUserName);
System.out.println(userInfo.getUserName());
}
使用案例:
在公司实习的时候,公司组件封装了@DistributedLock
注解来管理分布式锁,而锁key则是根据加锁对象类型的不同而有不同取值,但是由于注解的属性值只能是常量,不能直接等于成成员变量的值,这时候使用SpEL可以解决这问题
@DistributedLock(lockKey = "getType()")
@Override
public void doSomething(UserInfo userInfo) {
// ...
}
在这个例子中,他会在代理解析过程中调用被代理方法的第一个参数的指定方法,即lockKey
的值,也就是userInfo.getType()
来设置分布式锁的key,这样就能对加锁对象进行动态的调整
个人想法:
之前有个需求里需要根据用户的账号类型对账号的值执行不同的校验逻辑,当时想试着使用自定义校验注解实现,但是由于注解中的属性赋值不能是变量,所以无法动态获取实体类的状态类型,现在学了SpEL,可以使用SpEL的方式来实现该功能了