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

  1. package edu.pri.lime._7_12_1.main;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.Date;
  5. import java.util.List;
  6.  
  7. import org.springframework.expression.EvaluationContext;
  8. import org.springframework.expression.Expression;
  9. import org.springframework.expression.ExpressionParser;
  10. import org.springframework.expression.spel.standard.SpelExpressionParser;
  11. import org.springframework.expression.spel.support.StandardEvaluationContext;
  12.  
  13. import edu.pri.lime._7_12_1.bean.Person;
  14.  
  15. public class SpELTest {
  16.  
  17. public static void main(String[] args){
  18. // 创建一个ExpressionParser对象,用于接卸表达式
  19. ExpressionParser parser = new SpelExpressionParser();
  20. // 最简单的字符串表达式
  21. Expression exp = parser.parseExpression("'HelloWorld'");
  22. System.out.println("'HelloWorld' 的结果 : " + exp.getValue());
  23. // 调用方法的表达式
  24. exp = parser.parseExpression("'HelloWorld'.concat('!')");
  25. System.out.println("'HelloWorld'.concat('!') 的结果 : " + exp.getValue());
  26. // 调用对象的getter方法
  27. exp = parser.parseExpression("'HelloWorld'.bytes");
  28. System.out.println("'HelloWorld'.bytes 的结果 : " + exp.getValue());
  29. // 访问对象的属性(相当于HelloWorld.getBytes().length)
  30. exp = parser.parseExpression("'HelloWorld'.bytes.length");
  31. System.out.println("'HelloWorld'.bytes.length 的结果 : " + exp.getValue());
  32. // 使用构造器来创建对象
  33. exp = parser.parseExpression("new String('HelloWorld')" + ".toUpperCase()");
  34. System.out.println("new String('HelloWorld')" + ".toUpperCase() 的结果是 : " + exp.getValue());
  35. Person person = new Person(1,"孙悟空", new Date());
  36. exp = parser.parseExpression("name");
  37. System.out.println("以Person为root,name表达式的值是 : " + exp.getValue(person, String.class));
  38. exp = parser.parseExpression("name == '孙悟空'");
  39. StandardEvaluationContext ctx = new StandardEvaluationContext();
  40. // 将person设为Context的root对象
  41. ctx.setRootObject(person);
  42. // 以指定Context来计算表达式的值
  43. System.out.println(exp.getValue(ctx,Boolean.class));
  44. List<Boolean> list = new ArrayList<Boolean>();
  45. list.add(true);
  46. EvaluationContext ctx_ = new StandardEvaluationContext();
  47. // 将list设置成EvaluationContext的一个变量
  48. ctx_.setVariable("list", list);
  49. // 修改list变量的第一个元素的值
  50. parser.parseExpression("#list[0]").setValue(ctx_, "false");
  51. // list集合的第一个元素被改变
  52. System.out.println("list集合的第一个元素为 : " + parser.parseExpression("#list[0]").getValue(ctx_));
  53. }
  54. }

        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

  1. package edu.pri.lime._7_12_2.bean.impl;
  2.  
  3. import java.util.List;
  4.  
  5. import edu.pri.lime._7_12_2.bean.Axe;
  6. import edu.pri.lime._7_12_2.bean.Person;
  7.  
  8. public class Author implements Person {
  9.  
  10. private Integer id;
  11. private String name;
  12. private List<String> books;
  13. private Axe axe;
  14. public void useAxe(){
  15. System.out.println("我是" + name + ",正在砍柴\n" + axe.chop());
  16. System.out.println("稍后我会看两本名字:" + books + "的书");
  17. }
  18. public Integer getId() {
  19. return id;
  20. }
  21. public void setId(Integer id) {
  22. this.id = id;
  23. }
  24. public String getName() {
  25. return name;
  26. }
  27. public void setName(String name) {
  28. this.name = name;
  29. }
  30. public List<String> getBooks() {
  31. return books;
  32. }
  33. public void setBooks(List<String> books) {
  34. this.books = books;
  35. }
  36. public Axe getAxe() {
  37. return axe;
  38. }
  39. public void setAxe(Axe axe) {
  40. this.axe = axe;
  41. }
  42.  
  43. }

        XML :

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

        Class : SpringTest

  1. package edu.pri.lime._7_12_2.main;
  2.  
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5.  
  6. import edu.pri.lime._7_12_2.bean.Person;
  7. import edu.pri.lime._7_12_2.bean.impl.Author;
  8.  
  9. public class SpringTest {
  10.  
  11. public static void main(String[] args){
  12. ApplicationContext ctx = new ClassPathXmlApplicationContext("app_7_12_2.xml");
  13. Person author = ctx.getBean("author",Author.class);
  14. author.useAxe();
  15. }
  16. }

        Console :

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

      7.12.3 SpEL语法详述

        1.直接量表达式

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

          

  1. // 使用直接量表达式
  2. ExpressionParser parser = new SpelExpressionParser();
  3. Expression exp = null;
  4. exp = parser.parseExpression("'Hello World!'");
  5. System.out.println(exp.getValue());
  6. exp = parser.parseExpression("new java.util.Date()");
  7. System.out.println(exp.getValue());
  8. exp = parser.parseExpression("1");
  9. System.out.println(exp.getValue());
  10. exp = parser.parseExpression("true");
  11. System.out.println(exp.getValue());
  12. exp = parser.parseExpression("null");
  13. System.out.println(exp.getValue());

        2.在表达式中创建数组

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

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

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

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

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

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

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

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

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

        5.调用方法

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

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

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

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

        7.类型运算符

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

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

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

        8.调用构造器

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

  1. // 创建对象
  2. System.out.println(parser.parseExpression("new String('HelloWorld').substring(2,4)").getValue());
  3. 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...的更多相关文章

  1. 7 -- Spring的基本用法 -- 12... Spring 3.0 提供的表达式语言(SpEL)

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

  2. SpringMVC +mybatis+spring 结合easyui用法及常见问题总结

    SpringMVC +mybatis+spring 结合easyui用法及常见问题总结 1.FormatString的用法. 2.用postAjaxFillGrid实现dataGrid 把form表单 ...

  3. Spring MVC 学习笔记12 —— SpringMVC+Hibernate开发(1)依赖包搭建

    Spring MVC 学习笔记12 -- SpringMVC+Hibernate开发(1)依赖包搭建 用Hibernate帮助建立SpringMVC与数据库之间的联系,通过配置DAO层,Service ...

  4. Spring中@Async用法详解及简单实例

    Spring中@Async用法 引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类 ...

  5. (转)Spring中@Async用法总结

     原文:http://blog.csdn.net/blueheart20/article/details/44648667 引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的: ...

  6. Spring中@Async用法总结

    引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在Spring 3. ...

  7. spring AOP的用法

    AOP,面向切面编程,它能把与核心业务逻辑无关的散落在各处并且重复的代码给封装起来,降低了模块之间的耦合度,便于维护.具体的应用场景有:日志,权限和事务管理这些方面.可以通过一张图来理解下: Spri ...

  8. Spring常用注解用法总结

    转自http://www.cnblogs.com/leskang/p/5445698.html 1.@Controller 在SpringMVC 中,控制器Controller 负责处理由Dispat ...

  9. Spring中@Value用法收集

    一.配置方式 @Value需要参数,这里参数可以是两种形式: @Value("#{configProperties['t1.msgname']}") 或者 @Value(" ...

随机推荐

  1. Call an activity method from a fragment

    From fragment to activty: ((YourActivityClassName)getActivity()).yourPublicMethod(); From activity t ...

  2. css05 字体以及行间距

    <head><meta charset="utf-8"><title>无标题文档</title><style>#box{ ...

  3. java 使用对象

    class XiyoujiRenwu { float height,weight; String head, ear; void speak(String s) { head="歪着头&qu ...

  4. jpda

    http://www.ibm.com/developerworks/cn/java/j-lo-jpda1/ 远程调试用rmi通信,被调试端需要启动一个调试服务器,用命令jsadebugd. java/ ...

  5. 加密Web.Config配置文件

    protected void btnPassWord_Click(object sender, EventArgs e) { //加密 Configuration config = WebConfig ...

  6. js中如何获取时间

    var myDate = new Date();myDate.getYear();        //获取当前年份(2位)myDate.getFullYear();    //获取完整的年份(4位,1 ...

  7. keyCode码集合

    keycode 8 = BackSpace BackSpace keycode 9 = Tab Tab keycode 12 = Clear keycode 13 = Enter keycode 16 ...

  8. 我有一壶酒 Android学习之Service(1)--->BinderService方式

    本文只讨论扩展Binder类 创建一个Binder.xml <?xml version="1.0" encoding="utf-8"?> <L ...

  9. java中“==”和equal区别

    8个月以后就要正式找工作啦,我觉得现在是时候花时间好好深入研究一下以前比较混肴的知识.这就当作是自我成长的第一步! 对于String中的“equal方法”和“==”一直有点混肴,今天重新看了一下他们两 ...

  10. 执行 apt-get -f install 提示错误

    执行 apt-get -f install 提示错误 分类: Linux 2015-01-24 21:26 554人阅读 评论(0) 收藏 举报 1. 问题: usloft1359:~# rvm in ...