1.什么是SpEL表达式

SpEL表达式语言是一种表达式语言,是一种可以与一个基于spring的应用程序中的运行时对象交互的东西。有点类似于ognl表达式。总得来说SpEL表达式是一种简化开发的表达式,通过使用表达式来简化开发,减少一些逻辑、配置的编写。

2.SpEL表达式语言入门程序

xml配置的方式:

配置环境:pom.xml

  1. <dependencies>
  2. <dependency>
  3. <groupId>junit</groupId>
  4. <artifactId>junit</artifactId>
  5. <version>4.11</version>
  6. <scope>test</scope>
  7. </dependency>
  8. <dependency>
  9. <groupId>org.springframework</groupId>
  10. <artifactId>spring-core</artifactId>
  11. <version>4.0.5.RELEASE</version>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.springframework</groupId>
  15. <artifactId>spring-expression</artifactId>
  16. <version>4.0.5.RELEASE</version>
  17. </dependency>
  18. <dependency>
  19. <groupId>org.springframework</groupId>
  20. <artifactId>spring-context</artifactId>
  21. <version>4.0.5.RELEASE</version>
  22. </dependency>
  23. <dependency>
  24. <groupId>org.springframework</groupId>
  25. <artifactId>spring-beans</artifactId>
  26. <version>4.0.5.RELEASE</version>
  27. </dependency>
  28. </dependencies>

applicationContext.xml文件:

  1. <bean id="MyMessage" class="cn.spy.spel.injection.MyMessage">
  2. <property name="message" value="#{systemProperties['user.language']}"></property>
  3. </bean>

MyMessage.java文件:

  1. public class MyMessage {
  2. private String message;
  3. public String getMessage() {
  4. return message;
  5. }
  6. public void setMessage(String message) {
  7. this.message = message;
  8. }
  9. }

测试程序:

  1. public class Test {
  2. public static void main(String[] args) {
  3. ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml");
  4. MyMessage myMessage =context.getBean(MyMessage.class);
  5. System.out.println(myMessage.getMessage());
  6. }
  7. }

结果:

Spring之SpEL表达式 - 图1

解释:这里使用了表达式#{systemProperties[‘user.language’]}来设置值,用来检索用户语言系统的属性。

采用注解的方式

applicationContext.xml文件:

  1. <context:component-scan base-package="cn.spy.spel"></context:component-scan>

MyMessage2.java文件:

  1. @Component
  2. public class MyMessage2 {
  3. @Value("#{systemProperties['user.language']}")
  4. private String message;
  5. public String getMessage() {
  6. return message;
  7. }
  8. }

解释:这里使用了@Value注解的方式,当实例化MyMessage2这个bean的时候,将使用该注解设置默认值。此处还是使用了之前的SpEL表达式,来设置用户语言系统的属性。(在这里@Value注解既可以在类的字段属性上面,也可以在构造函数和方法上面使用)。

测试:

  1. public static void main(String[] args) {
  2. ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml");
  3. MyMessage2 myMessage =context.getBean(MyMessage2.class);
  4. System.out.println(myMessage.getMessage());
  5. }

结果:

Spring之SpEL表达式 - 图2

3.分析器

SpEL上下文中所定义的每一个表达式都应该首先被解析,然后在被评估。解析的过程采用了ExpressionParser接口的分析器进行处理的。SpelExpressionParser主要负责将字符串表达式解析到已编译的Expression对象中。(创建的分析器实例是线程安全)

代码形式:

  1. ExpressionParser parser =new SpelExpressionParser();

注意:

在SpEL表达式中,默认情况下,表达式前缀为 ‘ # ‘ ,而后缀为 ‘ } ‘ 。如果表达式中没有前缀和后缀,那么表达式字符串就被当作纯文本。

分析器解析Spel中纯文本表达式HelloWorld:

  1. public class HelloWorldTest {
  2. ExpressionParser parser;
  3. @Before
  4. public void setup(){
  5. //初始化创建SpEL表达式解析器
  6. parser =new SpelExpressionParser();
  7. }
  8. @Test
  9. public void test(){
  10. //使用解析器解析出表达式exp
  11. Expression exp=parser.parseExpression("'Hello World'");
  12. //在表达式中获取指定类型的值
  13. String value =exp.getValue(String.class);
  14. assertThat(value ,is("Hello World"));
  15. }
  16. }

junit测试结果:

Spring之SpEL表达式 - 图3

4.使用SpEL表达式调用方法

使用SpEL调用普通方法

就是SpEL也支持在表达式中采用方法调用的形式

范例:

User.java:

  1. public class User {
  2. private String username;
  3. private String password;
  4. public void setUsername(String username) {
  5. this.username = username;
  6. }
  7. public void setPassword(String password) {
  8. this.password = password;
  9. }
  10. public String getUsername() {
  11. return "李四";
  12. }
  13. public String getPassword() {
  14. return "lisi123";
  15. }
  16. public void printUser(){
  17. System.out.println("当前用户的用户名:"+username+" ,密码:"+password);
  18. }
  19. }

applicationContext.xml配置文件:

  1. <bean id="user1" class="cn.spy.spel.method.User">
  2. <property name="username" value="张三"></property>
  3. <property name="password" value="zhangsan123"></property>
  4. </bean>
  5. <bean id="user2" class="cn.spy.spel.method.User">
  6. <property name="username" value="#{user2.getUsername()}"></property>
  7. <property name="password" value="#{user2.getPassword()}"></property>
  8. </bean>

测试:

  1. public class TestMethod {
  2. public static void main(String[] args) {
  3. ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml");
  4. User user1 =(User) context.getBean("user1");
  5. user1.printUser();
  6. User user2 =(User) context.getBean("user2");
  7. user2.printUser();
  8. }
  9. }

结果:

Spring之SpEL表达式 - 图4

使用SpEL调用构造方法

  1. @Test
  2. public void test(){
  3. ExpressionParser parser =new SpelExpressionParser();
  4. Expression exp=parser.parseExpression("new Double(3.1415926)");
  5. Double value =exp.getValue(Double.class);
  6. assertThat(value ,is(3.1415926));
  7. }

结果:

Spring之SpEL表达式 - 图5

使用SpEL调用静态方法

  1. @Test
  2. public void test(){
  3. ExpressionParser parser =new SpelExpressionParser();
  4. Expression exp=parser.parseExpression("T(java.lang.Math).abs(-1)");
  5. Integer value =exp.getValue(Integer.class);
  6. assertThat(value ,is(1));
  7. }

结果:

Spring之SpEL表达式 - 图6

5.使用SpEL表达式调用变量和函数

(1)#变量的表达式使用

SpEL使用上下文StandardEvaluationContext查找表达式中存在的变量。在表达式中使用变量名称前添加一个标签前缀#,使用已注册的变量。

  1. public class TestSpEL {
  2. @Test
  3. public void test(){
  4. ExpressionParser parser =new SpelExpressionParser();
  5. StandardEvaluationContext context =new StandardEvaluationContext();
  6. context.setVariable("message", "Hello World");
  7. String value =parser.parseExpression("#message").getValue(context, String.class);
  8. assertThat(value, is("Hello World"));
  9. }
  10. }

结果:

Spring之SpEL表达式 - 图7

(2)#root表达式的使用

可以在上下文中设置一个对象评估,可以使用#root访问该对象。

  1. public class TestSpEL {
  2. @Test
  3. public void test(){
  4. ExpressionParser parser =new SpelExpressionParser();
  5. StandardEvaluationContext context =new StandardEvaluationContext();
  6. context.setRootObject(new Var());
  7. Assert.assertTrue(parser.parseExpression("#root").getValue(context) instanceof Var);
  8. }
  9. }

结果:

Spring之SpEL表达式 - 图8

(3)访问系统的属性和环境

SpEL预定义变量:systemProperties和systemEnvironment

  1. parser.parseExpression("@systemProperties['java.version']").getValue(context);
  2. parser.parseExpression("@systemProperties[JAVA_HOME]").getValue(context);

6.使用SpEL表达式中的运算符

SpEL提供了多种运算符。

类型 运算符
关系 <,>,<=,>=,==,!=,lt,gt,le,ge,eq,ne
算术 +,- ,* ,/,%,^
逻辑 &&,||,!,and,or,not,between,instanceof
条件 ?: (ternary),?: (elvis)
正则表达式 matches
其他类型 ?.,?[…],![…],[1]
,$[…]

注意:如果解析表达式时,在完全限定的类名中包含一个运算符的文本表示形式,则会产生异常。

正则表达式运算符matches

  1. @Test
  2. public void test(){
  3. ExpressionParser parser =new SpelExpressionParser();
  4. assertThat(parser.parseExpression("35 matches '[0-9]+'").getValue(Boolean.class), is(true));
  5. }

结果:

Spring之SpEL表达式 - 图9

逻辑运算符between

  1. @Test
  2. public void test(){
  3. ExpressionParser parser =new SpelExpressionParser();
  4. assertThat(parser.parseExpression("3 between {2,5}").getValue(Boolean.class), is(true));
  5. }

结果:

Spring之SpEL表达式 - 图10


  1. ↩︎