第四课 SpringEL表达式

Sping动态表达式语言(简称SpringEL)是一个运行时查询和操作对象的强大动态语言。
其语法类似于EL表达式,具有显示诸如显式方法调用和基本的字符串模板函数等。

JVM动态语言

java是一门强类型的静态语言,所有代码在运行之前都必须进行严格的类型检查并编译成JVM字节码,因此虽然在安全、性能方面得到了保证,但是牺牲了灵活性,这个特征就决定了java在语言层面无法直接进行表达式语句的动态解析。而动态语言恰恰相反,其显著的特点是在程序运行时可以改变程序结构或者变量类型。典型的动态语言有Ruby、Python、JavaScript、Perl等。这些动态语言能够广泛的被应用的许多领域,得益于其动态、简单、灵活等特性。因为他们无需编译即可被解释执行,它们可以在运行时动态的改变表达式语句。非常适合编写复杂的动态表达式。

java在实现复杂的业务系统、大型商业系统、分布式系统及中间件方面有着非常强的优势,但在开发这些系统的过程中,有时需要引用动态语言的一些特性,以弥补其在动态方面的不足,特别是在解决一些商业系统中动态规则的解析需求,如积分规则,各类套餐计费、活动促销等规则。

SpringEL表达式

spEL作为Spring家族中表达式求值的基础,它不直接依赖于Sping框架,可独立使用。只是在基于Spring框架使用spEL更加便捷,一般情况下无需手工调用spEl提供的API。因为Spring框架已经提供了许多直接使用的SpEL表达式的方法,并在框架层面屏蔽了表达式的运行设施创建过程,直接使用即可,例如在Bean配置定义中直接使用“#{}”编写SpringEL表达式。


	    org.springframework
	    spring-expression
	    5.1.9.RELEASE
	
	SpEL被设计成一个可独立运行的模块,可以脱离Spring容器直接运行,因此只需要引入SpEL的模块
	spring-expression依赖即可,无需引入Spring框架的其他模块。

public class MyTest2{
	public static void main(String[] arg) throws Exception {
		ExpressionParser eParser=new SpelExpressionParser();
		Expression express=eParser.parseExpression("'Hello'+'World'");
		String message=(String) express.getValue();
		System.out.println(message);
	}
}
在SpEL中,使用表达式非常简单,只需要创建一个SpelExpressionParser实例即可,也就是首先创建一个
SpEL表达式解析器,然后调用parseExpression()方法对表达式进行解析。其中单引号表示String类型。
Spring核心接口

SpringEL所有的类和接口都定义在org.springframework.expression包及其子包中,以及spel。support中。
ExpressionParser接口用来解析表达式字符串,表达式字符串是一个用单引号标注或者用转义字符双引号标注的字符串。
Expression接口用来计算表达式字符串的值,当调用parseExpression()或者getValue()方法时可能抛出解析异常和求值异常,因此在手工调用这些API时,需要处理这些可能的异常。
Spring支持一系列的功能特性,如方法调用、属性调用、字符串调用等。

public class MyTest2{
	public static void main(String[] arg) throws Exception {
		ExpressionParser eParser=new SpelExpressionParser();
		Expression express=eParser.parseExpression("'HelloWorld'.concat('!')");
		String message=express.getValue(String.class);
		System.out.println(message);
	}
}
结果:
HelloWorld!

在SpringEl中最常见的是对属性进行求值,例如获取User实例name属性值。

public class MyTest2{
	public static void main(String[] arg) throws Exception {
		User user=new User();
		user.setName("Mr.Ming");
		ExpressionParser parser=new SpelExpressionParser();
		EvaluationContext context=new StandardEvaluationContext(user);
		String name=(String) parser.parseExpression("name").getValue(context);
		System.out.println(name);
	}
}
在创建StandardEvaluationContext实例时,指定一个根对象作为求值的目标对象,这样在求值表达式中
,就可以引用根对象属性,在求值内部可以使用反射机制从注册对象中获取相应的属性值。

在单独使用SpEL时,需要创建一个ExpressionParser 解析器,并提供一个EvaluationContext求值
上下文。在普通的基于Spring应用开发中,这些API一般会很少涉及,仅需要编写SpEL表达式字符串即可,
至于解析器、求值上下文、根对象和其它预定义变量等基础设施,Spring都会创建。

EvaluationContext接口
EvaluationContext提供了属性、方法、字段解析器及类型转换器,默认实现类StandardEvaluationContext内部使用反射机制来操作对象,为了提高性能,在其内部会对已获取的Method、Field和Constructor实例进行缓存。

文本字符解析

public class MyTest2{
	public static void main(String[] arg) throws Exception {
		ExpressionParser parser=new SpelExpressionParser();
		//字符串解析
		String name=(String) parser.parseExpression("\"Hello\"").getValue();
		System.out.println(name);
		//double解析
		double doubleNumber=(double) parser.parseExpression("6.1235489E+12")
		.getValue();
		System.out.println(doubleNumber);
		//int解析
		int intNumber=(int) parser.parseExpression("1234").getValue();
		System.out.println(intNumber);
		//boolean解析
		boolean bool=(boolean) parser.parseExpression("true").getValue();
		System.out.println(bool);
		//null解析
		Object nullNum=(Object) parser.parseExpression("null").getValue();
		System.out.println(nullNum);
		
	}
}
结果:
Hello
6.1235489E12
1234
true
null

对象解析

public class MyTest2{
	public static void main(String[] arg) throws Exception {
		User user=new User();
		user.setName("Mr.Li");
		user.setAge(1);
		user.setAddress("BeiJing-City");
		ExpressionParser parser=new SpelExpressionParser();
		EvaluationContext context=new StandardEvaluationContext(user);
		String name=(String) parser.parseExpression("name").getValue(context);
		int age=(int) parser.parseExpression("age+18").getValue(context);
		System.out.print(name+"---"+age);
	}
}
结果:
无参构造函数--
Mr.Li---19

数组集合类型解析

public class MyTest2{
	public static void main(String[] arg) throws Exception {
	User user=new User();
	ExpressionParser parser=new SpelExpressionParser();
	EvaluationContext context=new StandardEvaluationContext(user);
int array[]=(int[]) parser.parseExpression("new int[]{1,2,3,4}")
.getValue(context);
//目前不支持多维数组初始化,就是二维以上的数组就不能再这里初始化
String arr[][]=(String[][]) parser.parseExpression
("new String[2][3]").getValue(context);
List list=(List) parser.parseExpression("{1,2,3,4}").getValue(context);
Map map=(Map) parser.parseExpression("{name:'tom',age:100}").getValue(context);
System.out.print(array[0]+"---"+arr[0][1]+"---"+list.size()+"--"+map.get("age"));
	}
}
结果:
无参构造函数--
1---null---4--100
方法解析

操作符解析

逻辑操作符解析

算术运算符解析
第四课 SpringEL表达式_第1张图片

安全导航操作符

三元操作符

赋值、类型、构造器、变量


在Spring中使用SpEL

在XML配置方式或注解配置方式中都可以使用SpEL表达式进行一些高级配置,两种方式都采用统一的语法使用SpEL表达式:#{表达式}

你可能感兴趣的:(Spring,SpringEL表达式)