博客
关于我
Spring 5 中文解析之核心篇-表达式(SpEL)
阅读量:711 次
发布时间:2019-03-21

本文共 3968 字,大约阅读时间需要 13 分钟。

Spring 表达式语言(SpEL)入门介绍

Spring Expression Language(简称 SpEL)是一种强大且灵活的表达式语言,由 Spring Framework 开发,广泛应用于运行时对象的查询和操作。它在 Spring 社区中的多个产品组合中都有广泛的支持,是定义 Bean 的表达方式的一种重要工具。以下将详细介绍 SpEL 的基本功能、使用方法以及在实际应用中的示例。


SpEL 的基本特性

SpEL 的语法类似于 Java 的 EL(Expression Language),但扩展了许多功能,主要包括以下几个方面:

1. 方法调用

SpEL 支持在表达式中直接调用方法,例如:

ExpressionParser parser = new SpelExpressionParser();Expression exp = parser.parseExpression("'Hello World'.concat('!')");String message = (String) exp.getValue();

输出结果为 "Hello World!"。

2. 属性访问

属性可以通过点号访问,例如:

ExpressionParser parser = new SpelExpressionParser();EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();Inventor tesla = new Inventor("Nikola Tesla", "Serbian");String name = (String) parser.parseExpression("name").getValue(tesla);// 结果:name == "Nikola Tesla"

3. 数字和字符串操作

支持基本的数字运算、四舍五入、指数运算等,以及字符串的构造函数操作,例如:

ExpressionParser parser = new SpelExpressionParser();String upperCase = parser.parseExpression("new String('hello world').toUpperCase()").getValue(String.class);// 结果:"HELLO WORLD"

4. 类型转换

SpEL 支持通过 ConversionService 进行类型转换,例如:

class Simple {    public List
booleanList = new ArrayList<>();}Simple simple = new Simple();simple.booleanList.add(true); EVALUATION_CONTEXT配置为只读访问模式:EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();parser.parseExpression("booleanList[0]").setValue(context, simple, "false")// 结果:trueBoolean b = simple.booleanList.get(0);

5. 集合和映射操作

支持内联列表和映射,例如:

ExpressionParser parser = new SpelExpressionParser();List numbers = parser.parseExpression("{1,2,3,4}").getValue(List.class);List
list = parser.parseExpression("{'a','b'}").getValue(List.class);

SpEL 的主要用法

1. 在 Bean 定义中的应用

在 XML 或注解配置中使用 SpEL 表达式指定属性值或构造函数参数,例如:

或者使用注解:

public class ExampleBean {    @Value("#{ systemProperties['user.region'] }")    private String defaultLocale;}

2. 作为表达式评估工具

通过 SpEL 表达式可以对对象进行各种操作,例如评估布尔逻辑:

ExpressionParser parser = new SpelExpressionParser();EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();boolean isMember = parser.parseExpression("isMember('Nikola Tesla')").getValue(context, Boolean.class);

3. 方法调用和变量使用

可以通过 #variable 来引用变量,并在表达式中使用安全导航操作符避免 NullPointer:

EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();context.setVariable("queryName", "Nikola Tesla");Expression expression = parser.parseExpression("Name == 'IEEE' and isMember(#queryName)");String result = parser.parseExpression(expression).getValue(context, String.class);

SpEL 的核心组件

1. 解析器(ExpressionParser)

负责解析 SpEL 表达式字符串,例如:

ExpressionParser parser = new SpelExpressionParser();Expression exp = parser.parseExpression("'Hello World'");Object value = exp.getValue(); // 返回 "Hello World"

2. 评估上下文(EvaluationContext)

用于管理评估过程中的变量和类型转换策略。主要实现包括 SimpleEvaluationContextStandardEvaluationContext

3. 转换服务(ConversionService)

默认使用 Spring 内核的转换服务,可自定义扩展以支持特定类型转换。


SpEL 的编译器

从 Spring 4.1 开始,SpEL 提供了编译器来提高表达式评估的性能。编译器关心项目的动态性和稳定性,适用于高性能需求的场景,但无法编译所有类型复杂的表达式,主要适用于以下情况:

编译模式

  • OFF:少互动时使用。
  • IMMEDIATE:在第一次评估后立即编译。
  • MIXED:在多次评估后动态切换编译模式。

配置方式

通过 SpelParserConfiguration 配置编译模式和类加载器,例如:

SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, this.getClass().getClassLoader());SpelExpressionParser parser = new SpelExpressionParser(config);

SpEL 的实际应用示例

示例 1:评估属性值

Inventor inventor = new Inventor("Nikola Tesla");EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();String fullName = parser.parseExpression("name").getValue(inventor, String.class);// 结果:"Nikola Tesla"

示例 2:复杂表达式

List
numbers = parser.parseExpression("8 / 5 % 2").getValue(List.class);// 结果:[1]

SpEL 的优势

  • 灵活性:支持多种操作,包括方法调用、属性访问、布尔逻辑、集合操作等。
  • 安全性:通过安全导航操作符避免 NullPointer 错误。
  • 高性能:使用编译器大幅提升评估性能。
  • 通用性:适用于 XML、注解配置以及其他 Spring 组件。

  • 总结

    SpEL 是 Spring 表达式语言的核心工具,广泛应用于对象的动态操作、属性访问以及数据绑定。通过合理使用 SpEL,开发者可以大大提升代码的灵活性和 maintainability。如果需要更详细的技术文档,可以参考 Spring 官方资料或相关技术博客。

    转载地址:http://oldrz.baihongyu.com/

    你可能感兴趣的文章
    MySQL 中日志的面试题总结
    查看>>
    mysql 中的all,5分钟了解MySQL5.7中union all用法的黑科技
    查看>>
    MySQL 中的外键检查设置:SET FOREIGN_KEY_CHECKS = 1
    查看>>
    Mysql 中的日期时间字符串查询
    查看>>
    mysql 中索引的问题
    查看>>
    MySQL 中锁的面试题总结
    查看>>
    MySQL 中随机抽样:order by rand limit 的替代方案
    查看>>
    MySQL 为什么需要两阶段提交?
    查看>>
    mysql 为某个字段的值加前缀、去掉前缀
    查看>>
    mysql 主从
    查看>>
    mysql 主从 lock_mysql 主从同步权限mysql 行锁的实现
    查看>>
    mysql 主从互备份_mysql互为主从实战设置详解及自动化备份(Centos7.2)
    查看>>
    mysql 主从关系切换
    查看>>
    MYSQL 主从同步文档的大坑
    查看>>
    mysql 主键重复则覆盖_数据库主键不能重复
    查看>>
    Mysql 事务知识点与优化建议
    查看>>
    Mysql 优化 or
    查看>>
    mysql 优化器 key_mysql – 选择*和查询优化器
    查看>>
    MySQL 优化:Explain 执行计划详解
    查看>>
    Mysql 会导致锁表的语法
    查看>>