SpEL使用详解

193 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

介绍

SpEL - Spring Expression Language,是一种强大的表达式语言,支持在运行时查询和操作对象图。

该语言是由Spring社区需求驱动,所以在Spring框架中使用是最合适的,因为这脚就是配着鞋长的。

最常见的使用方式,是用在xml或者java注解中。

该语言支持很多特性:

  • Literal expressions:字面量表达式
  • Boolean and relational operators: 布尔运算符和关系运算符
  • Regular expressions:正则表达式
  • Class expressions:类表达式
  • Accessing properties, arrays, lists, and maps:用于访问属性、数组、列表或集合
  • Method invocation:方法调用
  • Relational operators:关系运算符
  • Assignment:赋值
  • Calling constructors:调用构造函数
  • Bean references:引用Bean
  • Array construction:数组
  • Inline lists:内联列表
  • Inline maps:内联集合
  • Ternary operator:三元运算符
  • Variables:变量
  • User-defined functions:用户定义函数
  • Collection projection:集合投影
  • Collection selection:集合选择
  • Templated expressions:模板化表达式

SpEL 在 org.springframework.expression命名空间下 #演示几个实例

字面量表达式

ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("'Hello BetsyVR'");
expression.getValue()  // Hello BetsyVR

ExpressionParse 负责解析字面量表达式,Expression负责评估字面量表达式

方法调用

ExpressionParser parser = new SpelExpressionParser(); 
Expression exp = parser.parseExpression("'Hello World'.concat('!')"); 
String message = (String) exp.getValue(); //Hello World!

exp.getValue()默认返回Object,也可以使用泛型函数:exp.getValue(String.class)省去类型转换,这两个重载其实主要实现逻辑一样一样的,区别就是内部帮我们转换了一下,看源码:

再高级点的用法:

String word="betsy-VR";
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("length()");
expression.getValue(word); // 8

构造函数

ExpressionParser parser = new SpelExpressionParser(); 
Expression exp = parser.parseExpression("new String('hello world').toUpperCase()"); 
String message = exp.getValue(String.class); // HEELO WORLD

SpEL 还有很多复杂和高级的应用,比如上下文、配置解析等,但都不是很常用,感兴趣的可以到官网转转,接下来介绍常用的功能。

如何在Bean定义中使用

在基于xml或基于java注解定义bean时,都可以使用SpEL,而且语法相同,都是#{}格式。

所有注入到Application Context中的Bean都可以在SpEL中使用,包括SystemProperties和SystemEnvironment这类。


基于xml的例子

<bean id="numberGuess" class="org.spring.samples.NumberGuess"> 
    <property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/> 
    <!-- other properties --> 
</bean> 

<bean id="shapeGuess" class="org.spring.samples.ShapeGuess"> 
    <property name="initialShapeSeed" value="#{ numberGuess.randomNumber }"/> 
    <!-- other properties --> 
</bean>

在配置中,有一个 T()操作符,用来标记后面是一个类的实例或者静态类,SpEL中的TypeLocator会去查找相关的类,StandardTypeLocator可以明确该类所属命名空间,所以可以直接写类名就可以。

基于java注解的例子

public class FieldValueTestBean { 
    @Value("#{ systemProperties['user.region'] }") 
    private String defaultLocale; 
    public void setDefaultLocale(String defaultLocale) { 
        this.defaultLocale = defaultLocale; 
    } 

    public String getDefaultLocale() { return this.defaultLocale; } 
}