EvaluationContext 接口在评估表达式以解决属性、方法或字段时使用,并帮助执行类型转换。Spring 提供了两种实现:

  • SimpleEvaluationContext:暴露了 SpEL 语言的基本特征和配置选项的一个子集,适用于不需要SpEL 语言语法的全部范围并应受到有意义的限制的表达类别。例如,包括但不限于数据绑定表达式和基于属性的过滤器。
  • StandardEvaluationContext:暴露了全套的 SpEL 语言特性和配置选项。你可以用它来指定一个默认的根对象,并配置每个可用的评估相关策略。

SimpleEvaluationContext 被设计为只支持 SpEL 语言语法的一个子集。它排除了 Java 类型引用、构造函数和 Bean 引用。它还要求你明确选择对表达式中的属性和方法的支持程度。默认情况下,create()静态工厂方法只允许对属性进行读取访问。你也可以获得一个构建器来配置所需的确切支持级别,目标是以下的一个或一些组合:

  • 仅限自定义 PropertyAccessor(无反射)。
  • 用于只读访问的数据绑定属性
  • 读和写的数据绑定属性

类型转换

默认情况下,SpEL 使用 Spring 核心中提供的转换服务(org.springframework.core.convert.ConversionService)。这个转换服务为常见的转换提供了许多内置的转换器,但也是完全可扩展的,因此你可以添加类型之间的自定义转换。此外,它是泛型感知的。这意味着,当你在表达式中使用通用类型时, SpEL 会尝试进行转换以保持它所遇到的任何对象的类型正确性。

这在实践中是什么意思?假设赋值,使用 setValue(),被用来设置一个 List 属性。该属性的类型实际上是 List<Boolean>。SpEL 认识到,列表中的元素在被放入之前需要被转换为布尔值。下面的例子显示了如何做到这一点:

  1. package cn.mrcode.study.springdocsread.data;
  2. import org.springframework.expression.EvaluationContext;
  3. import org.springframework.expression.ExpressionParser;
  4. import org.springframework.expression.spel.standard.SpelExpressionParser;
  5. import org.springframework.expression.spel.support.SimpleEvaluationContext;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. /**
  9. * @author mrcode
  10. */
  11. public class DemoTest {
  12. public static void main(String[] args) {
  13. ExpressionParser parser = new SpelExpressionParser();
  14. Simple simple = new Simple();
  15. simple.booleanList.add(true);
  16. // 创建一个只读的数据绑定
  17. EvaluationContext context = SimpleEvaluationContext
  18. .forReadOnlyDataBinding()
  19. .build();
  20. // "false" 在这里是作为一个字符串传入的。
  21. // SpEL 和转换服务会认识到它需要是一个布尔值并进行相应的转换。
  22. parser.parseExpression("booleanList[0]").setValue(context, simple, "false");
  23. // 上面声明的是只读,但是上面这一条语句却做了写操作,而且也能写入,是不是很迷惑?
  24. // 你要注意的是:对于 list 这种引用类型来讲,是对 list 的写,而不是对 simple.booleanList 这个字段的写
  25. // 比如下面这一行:就是对 simple.booleanList 的写,就会报错了
  26. // parser.parseExpression("booleanList").setValue(context, simple, new ArrayList<>());
  27. // b = false
  28. Boolean b = simple.booleanList.get(0);
  29. System.out.println(b);
  30. }
  31. static class Simple {
  32. // 需要注意的是这个 方法权限,如果是 private 就会报错
  33. // 是 private 的话,如果你提供了 getter 方法 也算是公开方法
  34. public List<Boolean> booleanList = new ArrayList<Boolean>();
  35. }
  36. }