7.12 Spring 3.0 提供的表达式语言(SpEL)

    Spring表达式语言(简称SpEL)是一种与JSP 2 的EL功能类似的表达式语言,它可以在运行时查询和操作对象图。支持方法调用和基本字符串模板函数。

    SpEL 可以独立于Spring容器使用------只是当成简单的表达式语言来使用;也可以在Annotation或XML配置中使用SpEL,这样可以充分利用SpEL简化Spring的Bean配置。

      7.12.1 使用Expression接口进行表达式求值。

        Spring的SpEL 可以单独使用,可以使用SpEL对表达式计算、求值。

        SpEL主要提供了如下三个接口:

          ⊙ ExpressionParser : 该接口的实例负责解析一个SpEL表达式,返回一个Expression对象。

          ⊙ Expression : 该接口的实例代表一个表达式。

          ⊙ EvaluationContext : 代表计算表达式值的上下文。当SpEL表达式中含有变量时,程序将需要使用该API来计算表达式的值。

        Expression实例代表一个表达式,它包含了如下方法用于计算,得到表达式的值。

          ⊙ Object getValue() : 计算表达式的值。

          ⊙ <T> T getValue(Class<T> desiredResultType) : 计算表达式的值,而且尝试将该表达式的值当成desiredResultType类型处理。

          ⊙ Object getValue(EvaluationContext context) : 使用指定的EvaluationContext来计算表达式的值。

          ⊙ <T> T getValue(EvaluationContext context,Class<T> desiredResultType) : 使用指定的EvaluationContext来计算表达式的值,而且尝试将该表达式的值当成desiredResultType类型处理。

          ⊙ Object getValue(Object rootObject) : 以rootObject作为表达式的root对象来计算表达式的值。

          ⊙ <T> T getValue(Object rootObject , Class<T> desiredResultType) : 以rootObject 作为表达式的root对象来计算表达式的值,而且尝试将该表达式的值当场desiredResultType类型来处理。

        Class : SpELTest

package edu.pri.lime._7_12_1.main;

import java.util.ArrayList;
import java.util.Date;
import java.util.List; import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext; import edu.pri.lime._7_12_1.bean.Person; public class SpELTest { public static void main(String[] args){
// 创建一个ExpressionParser对象,用于接卸表达式
ExpressionParser parser = new SpelExpressionParser();
// 最简单的字符串表达式
Expression exp = parser.parseExpression("'HelloWorld'");
System.out.println("'HelloWorld' 的结果 : " + exp.getValue());
// 调用方法的表达式
exp = parser.parseExpression("'HelloWorld'.concat('!')");
System.out.println("'HelloWorld'.concat('!') 的结果 : " + exp.getValue());
// 调用对象的getter方法
exp = parser.parseExpression("'HelloWorld'.bytes");
System.out.println("'HelloWorld'.bytes 的结果 : " + exp.getValue());
// 访问对象的属性(相当于HelloWorld.getBytes().length)
exp = parser.parseExpression("'HelloWorld'.bytes.length");
System.out.println("'HelloWorld'.bytes.length 的结果 : " + exp.getValue());
// 使用构造器来创建对象
exp = parser.parseExpression("new String('HelloWorld')" + ".toUpperCase()");
System.out.println("new String('HelloWorld')" + ".toUpperCase() 的结果是 : " + exp.getValue());
Person person = new Person(1,"孙悟空", new Date());
exp = parser.parseExpression("name");
System.out.println("以Person为root,name表达式的值是 : " + exp.getValue(person, String.class));
exp = parser.parseExpression("name == '孙悟空'");
StandardEvaluationContext ctx = new StandardEvaluationContext();
// 将person设为Context的root对象
ctx.setRootObject(person);
// 以指定Context来计算表达式的值
System.out.println(exp.getValue(ctx,Boolean.class));
List<Boolean> list = new ArrayList<Boolean>();
list.add(true);
EvaluationContext ctx_ = new StandardEvaluationContext();
// 将list设置成EvaluationContext的一个变量
ctx_.setVariable("list", list);
// 修改list变量的第一个元素的值
parser.parseExpression("#list[0]").setValue(ctx_, "false");
// list集合的第一个元素被改变
System.out.println("list集合的第一个元素为 : " + parser.parseExpression("#list[0]").getValue(ctx_));
}
}

        EvaluationContext代表SpEL计算表达式值的“上下文”,这个Context对象可以包含多个对象,但只能有一个root(根)对象。当表达式中包含变量是,SpEL机会根据EvaluationContext中的变量的值对表达式进行计算。

        为了往EvaluationContext里放入对象(SpEL称之为变量),可以调用该对象的如下方法:

          ⊙ setVariable(String name,Object value) : 向EvaluationContext中放入value对象,该对象名为name。为了在SpEL访问EvaluationContext中指定对象,应采用与OGNL类是的格式:#name

        StandardEvaluationContext提供了如下方法来设置root对象。

          ⊙ setRootObject(Object rootObject)

        在SpEL中访问root对象的属性时,可以省略root对象的前缀:foo.bar 访问rootObject的foo属性的bar属性。、

        使用Expression对象计算表达式的值时,可以直接指定root对象:exp.getValue(person,String.class) 以person对象为root对象计算表达式的值。

      7.12.2 Bean定义中的表达式语言支持

        Spring允许在Bean定义中使用SpEL。在XML配置文件和Annotation中都可以使用SpEL。在XML配置文件和Annotation中使用SpEL时,在表达式外面增加#{}包围即可。

        Class : Author

package edu.pri.lime._7_12_2.bean.impl;

import java.util.List;

import edu.pri.lime._7_12_2.bean.Axe;
import edu.pri.lime._7_12_2.bean.Person; public class Author implements Person { private Integer id;
private String name;
private List<String> books;
private Axe axe;
public void useAxe(){
System.out.println("我是" + name + ",正在砍柴\n" + axe.chop());
System.out.println("稍后我会看两本名字:" + books + "的书");
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getBooks() {
return books;
}
public void setBooks(List<String> books) {
this.books = books;
}
public Axe getAxe() {
return axe;
}
public void setAxe(Axe axe) {
this.axe = axe;
} }

        XML :

<?xml version="1.0" encoding="UTF-8"?>
<!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 使用util:properties加载指定的资源文件 -->
<util:properties id="confTest" location="classpath:test_zh_CN.properties" />
<!--
配置setName()的参数时,在表达式中调研那个方法,
配置setAxe()的参数时,在表达式中创建对象
配置调用setBooks()的参数时,在表达式中访问其他Bean的属性 -->
<bean id="author" class="edu.pri.lime._7_12_2.bean.impl.Author"
p:name="#{T(java.lang.Math).random()}"
p:axe="#{new edu.pri.lime._7_12_2.bean.impl.SteelAxe()}"
p:books="#{{confTest.a,confTest.b}}" />
</beans>

        Class : SpringTest

package edu.pri.lime._7_12_2.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import edu.pri.lime._7_12_2.bean.Person;
import edu.pri.lime._7_12_2.bean.impl.Author; public class SpringTest { public static void main(String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("app_7_12_2.xml");
Person author = ctx.getBean("author",Author.class);
author.useAxe();
}
}

        Console :

我是0.04521700994046529,正在砍柴
用钢斧砍材真快
稍后我会看两本名字:[你好, 哈哈]的书

      7.12.3 SpEL语法详述

        1.直接量表达式

          直接量表达式是SpEL中最简单的表达式,直接量表达式就是在表达式中使用Java语言支持的直接量,包括字符串、日期、数值、boolean值和null。

          

//        使用直接量表达式
ExpressionParser parser = new SpelExpressionParser();
Expression exp = null;
exp = parser.parseExpression("'Hello World!'");
System.out.println(exp.getValue());
exp = parser.parseExpression("new java.util.Date()");
System.out.println(exp.getValue());
exp = parser.parseExpression("1");
System.out.println(exp.getValue());
exp = parser.parseExpression("true");
System.out.println(exp.getValue());
exp = parser.parseExpression("null");
System.out.println(exp.getValue());

        2.在表达式中创建数组

          SpEL表达式直接支持使用静态初始化、动态初始化两种语法来创建数组。

//            创建一个数组
exp = parser.parseExpression("new String[]{'java','Struts','Spring'}");
System.out.println(exp.getValue());
// 创建二维数组
exp = parser.parseExpression("new int[2][4]");
System.out.println(exp.getValue());

        3.在表达式中创建List集合

          SpEL直接使用如下语法来创建List集合:{ele1,ele2,ele3...}

//            创建一个集合
exp = parser.parseExpression("{'java','Struts','Spring'}");
System.out.println(exp.getValue());
// 创建二维集合
exp = parser.parseExpression("{{'lime','oracle'},{'java','Spring'}}");
System.out.println(exp.getValue());

        4.在表达式中访问List、Map等集合元素

          在SpEL中访问List集合的元素:#list[index]

          在SpEL中访问Map集合的元素:#map[key]

List<String> list = new ArrayList<String>();
list.add("Java");
list.add("Struts");
list.add("Spring");
Map<String,Double> map = new HashMap<String, Double>();
map.put("Java", 80.0);
map.put("Spring", 89.0);
// 创建一个EvaluationContext对象,作为SpEL解析变量的上下文
EvaluationContext ctx = new StandardEvaluationContext();
// 设置两个变量
ctx.setVariable("myList", list);
ctx.setVariable("myMap",map);
// 访问List集合的第二个元素
System.out.println(parser.parseExpression("#myList[1]").getValue(ctx));
// 访问Map集合的指定元素
System.out.println(parser.parseExpression("#myMap['Java']").getValue(ctx));

        5.调用方法

//            调用String对象的substring()方法
System.out.println(parser.parseExpression("'Hello World'.substring(2,5)").getValue());
List<String> list = new ArrayList<String>();
list.add("java");
list.add("springMVC");
list.add("spring");
list.add("myBatis");
// 创建一个EvaluationContext对象,作为SpEL解析变量的上下文
EvaluationContext ctx = new StandardEvaluationContext();
// 设置一个变量
ctx.setVariable("myList", list);
// 调用指定变量所代表对象的subList()方法
System.out.println(parser.parseExpression("#myList.subList(1,3)").getValue(ctx));

        6.算术、比较、逻辑、赋值、三目等运算符

          在SpEL中使用赋值运算符可以直接改变表达式所引用的实际对象。

List<String> list = new ArrayList<String>();
list.add("Java");
list.add("SpringMVC");
list.add("Spring");
list.add("MyBatis");
EvaluationContext ctx = new StandardEvaluationContext();
ctx.setVariable("myList", list);
// 对集合的第一个元素进行赋值
parser.parseExpression("#myList[0]='JavaLime'").getValue(ctx);
System.out.println(list.get(0));
// 使用三目运算符
System.out.println(parser.parseExpression("#myList.size() > 3 ? " + "'myList长度大于3' : 'myList长度不大于3'").getValue(ctx));

        7.类型运算符

          T():这个运算符用于告诉SpEL将该运算符内的字符串当成“类”处理,避免Spring对其进行其他解析。尤其是调用某个类的静态方法时。

//            调用Math的静态方法
System.out.println(parser.parseExpression("T(java.lang.Math).random()").getValue());
// 调用System的静态方法
System.out.println(parser.parseExpression("T(System).getProperty('os.name')").getValue());

          在表达式中使用某个类时,推荐使用该类的全限定类名。但如果只写类名,不写包名,SpEL也可以尝试处理,SpEL使用StandardTypeLocator去定位这些类,它默认会在java.lang包下找这些类。

        8.调用构造器

          SpEL允许在表达式中直接使用new来调用构造器,这种调用可以创建一个Java对象。

//            创建对象
System.out.println(parser.parseExpression("new String('HelloWorld').substring(2,4)").getValue());
System.out.println(parser.parseExpression("new javax.swing.JFrame('测试')" + ".setVisible('true')").getValue());

        9.变量

          SpEL允许通过EvaluationContext来使用变量,该对象包含了一个setVariable(String name,Object value)方法,该方法用于设置一个变量。在SpEL中通过#name来访问该变量。

          SpEL中有如下两个特殊的变量:

            ⊙ #this : 引用SpEL当前正在计算的对象。

            ⊙ #root :引用SpEL的EvaluationContext的root对象。

        10.自定义函数

啦啦啦

啦啦啦

啦啦啦

啦啦啦

7 -- Spring的基本用法 -- 12... Spring 3.0 提供的表达式语言(SpEL)的更多相关文章

  1. 7 -- Spring的基本用法 -- 12...

    7.12 Spring 3.0 提供的表达式语言(SpEL) Spring表达式语言(简称SpEL)是一种与JSP 2 的EL功能类似的表达式语言,它可以在运行时查询和操作对象图.支持方法调用和基本字 ...

  2. 7 -- Spring的基本用法 -- 6... Spring 3.0 提供的Java配置管理

    7.6 Spring 3.0 提供的Java配置管理 Spring 允许使用Java类进行配置管理,可以不使用XML来管理Bean,以及Bean之间的依赖关系. Interface :Person p ...

  3. 7 -- Spring的基本用法 -- 5... Spring容器中的Bean;容器中Bean的作用域;配置依赖;

    7.5 Spring容器中的Bean 7.5.1 Bean的基本定义和Bean别名 <beans.../>元素是Spring配置文件的根元素,该元素可以指定如下属性: default-la ...

  4. Spring学习记录(七)---表达式语言-SpEL

    SpEL---Spring Expression Language:是一个支持运行时查询和操作对象图表达式语言.使用#{...}作为定界符,为bean属性动态赋值提供了便利. ①对于普通的赋值,用Sp ...

  5. Spring表达式语言SpEL

    Spring表达式语言,简称SpEL,是一个支持运行时查询和操作对象图的强大的表达式语言.语法类似于EL:SpEL使用#{…}作为定界符,所有在大括号中的字符都将被认为是SpEL SpEL为bean属 ...

  6. Spring的3.0提供了一种:SpEL注入方式(了解)

    1. SpEL:Spring Expression Language是Spring的表达式语言,有一些自己的语法 2. 语法 * #{SpEL} 3. 例如如下的代码 <!-- SpEL的方式 ...

  7. Spring学习笔记--Spring表达式语言SpEL

    Spring3引入了Spring表达式语言(Spring Expression Language,SpEL).SpEL是一种强大的.简洁的装配Bean的方式,它通过运行期执行的表达式将值装配到Bean ...

  8. Spring表达式语言SpEL简单介绍

    Spring3引入了Spring表达式语言(Spring Expression Language,SpEL). SpEL有非常多特性.比較经常使用的包含: 1.使用bean的id来引用bean, 以下 ...

  9. Spring表达式语言:SpEl

    概念: 是一个支持运行时查询和操作的对象图的强大的表达式语言. 语法类似于EL:SpEl使用#{ ...}作为定界符,所有在大括号中的 字符都将被认为是SpEl SpEl为bean的属性进行动态赋值提 ...

随机推荐

  1. sqoop 兼容性问题

    --direct 只支持mysql 5.0 + 和postgresql 8.3+(只是import) jdbc的jar包需要放在$SQOOP_HOME/lib目录下 mysql zeroDateTim ...

  2. centos7安装rabbitmq3.7

    centos7安装rabbitmq3.7安装erlang # vim /etc/yum.repos.d/rabbitmq-erlang.repo [rabbitmq-erlang] name=rabb ...

  3. RGB转灰度图的几种算法

    https://blog.csdn.net/cool1949/article/details/6649429 方法一:    对于彩色转灰度,有一个很著名的心理学公式: Gray = R*0.299 ...

  4. STM32的TAMPER-RTC管脚作为Tamper的使用[转]

    问题一: 当 TAMPER引脚上的信号从 0变成1或者从 1变成 0(取决于备份控制寄存器BKP_CR的 TPAL位),会产生一个侵入检测事件.侵入检测事件将所有数据备份寄存器内容清除.   然而为了 ...

  5. Java ArrayList源码剖析

    转自: Java ArrayList源码剖析 总体介绍 ArrayList实现了List接口,是顺序容器,即元素存放的数据与放进去的顺序相同,允许放入null元素,底层通过数组实现.除该类未实现同步外 ...

  6. Windows IOT 开发入门(准备工作)

    终于抽出空来了,将最近研究的东西记录下来,物联网,万物皆可联网.然后可以做到智能家居,智能生活,智能城市....一大堆.吹牛的就不说了. 在实际应用中都是一个个小的传感器在收集数据,同时把数据直接或者 ...

  7. SpagoBI 教程 Lesson 3: Highchart Dashboards

    SpagoBI Lesson 3: Highchart Dashboards Business Intelligence dashboards Every car comes with a dash ...

  8. 【总结】牛客职播第九期:您的美团点评offer已送到门口,快来与我们一起影响世界!

    一.介绍 美团点评2018校园春招流程介绍&面试答疑 讲师:燕鹏.Taylor 二.收获 面试时如果太紧张或者内向,容易吃亏,所以建议把面试当做展示自己的一次舞台. 遇见一道编程题目,如果无法 ...

  9. 飞机找不到,流量哪去了?记一次移动WAP网关导致的问题

    这几天随着客户端一个新版本发布,运维发现CDN的流量猛跌: 话说流量就是金钱,流量就是工资.领导很生气,后果很严重.没什么好说的,赶紧查!一开始怀疑服务端有问题,先受伤的总是我们,当然这也是没错的,因 ...

  10. 如何使用Matrix对bitmap的旋转与镜像水平垂直翻转

    Bitmap convert(Bitmap a, int width, int height){int w = a.getWidth();int h = a.getHeight();Bitmap ne ...