信息发布→ 登录 注册 退出

spring之SpEL表达式详解

发布时间:2026-01-11

点击量:
目录
  • 1.什么是SpEL表达式
  • 2.SpEL表达式语言入门程序
    • (1)xml配置的方式
    • (2)采用注解的方式
  • 3.分析器
    • 4.使用SpEL表达式调用方法
      • (1)使用SpEL调用普通方法
      • (2)使用SpEL调用构造方法
      • (3)使用SpEL调用静态方法
    • 6.使用SpEL表达式调用变量和函数
      • (1)#变量的表达式使用
      • (2)#root表达式的使用
      • (3)访问系统的属性和环境
    • 7.使用SpEL表达式中的运算符

      1.什么是SpEL表达式

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

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

      (1)xml配置的方式

      配置环境:pom.xml

      <dependencies>
      		<dependency>
      			<groupId>junit</groupId>
      			<artifactId>junit</artifactId>
      			<version>4.11</version>
      			<scope>test</scope>
      		</dependency>
      		<dependency>
      			<groupId>org.springframework</groupId>
      			<artifactId>spring-core</artifactId>
      			<version>4.0.5.RELEASE</version>
      		</dependency>
      		<dependency>
      			<groupId>org.springframework</groupId>
      			<artifactId>spring-expression</artifactId>
      			<version>4.0.5.RELEASE</version>
      		</dependency>
      		<dependency>
      			<groupId>org.springframework</groupId>
      			<artifactId>spring-context</artifactId>
      			<version>4.0.5.RELEASE</version>
      		</dependency>
      		<dependency>
      			<groupId>org.springframework</groupId>
      			<artifactId>spring-beans</artifactId>
      			<version>4.0.5.RELEASE</version>
      		</dependency>
      </dependencies>

      applicationContext.xml文件:

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

      MyMessage.java文件: 

      public class MyMessage {
       
      	private String message;
       
      	public String getMessage() {
      		return message;
      	}
       
      	public void setMessage(String message) {
      		this.message = message;
      	}
      	
      }

      测试程序:

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

      结果:

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

      (2)采用注解的方式

      applicationContext.xml文件:

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

      MyMessage2.java文件:

      @Component
      public class MyMessage2 {
      	
      	@Value("#{systemProperties['user.language']}")
      	private String message;
       
      	public String getMessage() {
      		return message;
      	}
      }

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

      测试:

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

      结果:

      3.分析器

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

      代码形式:

      ExpressionParser parser =new SpelExpressionParser();

      注意:

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

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

      public class HelloWorldTest {
      	ExpressionParser parser;
      	
      	@Before
      	public void setup(){
      		//初始化创建SpEL表达式解析器
      		parser =new SpelExpressionParser();
      	}
      	
      	@Test
      	public void test(){
      		//使用解析器解析出表达式exp
      		Expression exp=parser.parseExpression("'Hello World'");
      		//在表达式中获取指定类型的值
      		String value =exp.getValue(String.class);
      		assertThat(value ,is("Hello World"));
      	}
      }

      junit测试结果:

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

      (1)使用SpEL调用普通方法

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

      范例:

      User.java:

      public class User {
      	
      	private String username;
      	private String password;
      	public void setUsername(String username) {
      		this.username = username;
      	}
      	public void setPassword(String password) {
      		this.password = password;
      	}
      	public String getUsername() {
      		return "李四";
      	}
      	public String getPassword() {
      		return "lisi123";
      	}
      	public void printUser(){
      		System.out.println("当前用户的用户名:"+username+" ,密码:"+password);
      	}
      }

      applicationContext.xml配置文件:

              <bean id="user1" class="cn.spy.spel.method.User">
      			<property name="username" value="张三"></property>
      			<property name="password" value="zhangsan123"></property>
      		</bean>		
      				
      		<bean id="user2" class="cn.spy.spel.method.User">
      			<property name="username" value="#{user2.getUsername()}"></property>
      			<property name="password" value="#{user2.getPassword()}"></property>
      		</bean>	

      测试:

      public class TestMethod {
      	public static void main(String[] args) {
      		ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml");
      		User user1 =(User) context.getBean("user1");
      		user1.printUser();
      		User user2 =(User) context.getBean("user2");
      		user2.printUser();
      	}
      }

      结果:

      (2)使用SpEL调用构造方法

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

      结果:

      (3)使用SpEL调用静态方法

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

      结果:

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

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

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

      public class TestSpEL {
      	@Test
      	public void test(){
      		ExpressionParser parser =new SpelExpressionParser();
      		StandardEvaluationContext context =new StandardEvaluationContext();
      		context.setVariable("message", "Hello World");
      		String value =parser.parseExpression("#message").getValue(context, String.class);
      		assertThat(value, is("Hello World"));
      	}
      }

      结果:

      (2)#root表达式的使用

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

      public class TestSpEL {
      	@Test
      	public void test(){
      		ExpressionParser parser =new SpelExpressionParser();
      		StandardEvaluationContext context =new StandardEvaluationContext();
      		context.setRootObject(new Var());
      		Assert.assertTrue(parser.parseExpression("#root").getValue(context) instanceof Var);
      	}
      }

      结果:

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

      SpEL预定义变量:systemProperties和systemEnvironment

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

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

      SpEL提供了多种运算符。

      类型

      运算符

      关系

      <,>,<=,>=,==,!=,lt,gt,le,ge,eq,ne

      算术

      +,- ,* ,/,%,^

      逻辑

      &&,||,!,and,or,not,between,instanceof

      条件

      ?: (ternary),?: (elvis)

      正则表达式

      matches

      其他类型

      ?.,?[…],![…],^[…],$[…]

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

      正则表达式运算符matches

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

      结果:

      逻辑运算符between

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

      结果:

      以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

      在线客服
      服务热线

      服务热线

      4008888355

      微信咨询
      二维码
      返回顶部
      ×二维码

      截屏,微信识别二维码

      打开微信

      微信号已复制,请打开微信添加咨询详情!