news 2026/8/27 3:43:02

SpEL 表达式详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpEL 表达式详解

SpEL表达式(Spring Expression Language)详解

SpEL(Spring Expression Language)是Spring框架提供的一种强大的表达式语言,用于在运行时查询和操作对象图,支持字面量、运算符、方法调用、属性访问、正则匹配、集合操作等,可独立使用或集成到Spring框架(如注解、XML配置、Bean定义)中。

一、核心特点

  1. 动态求值:运行时解析表达式,而非编译期;
  2. 跨场景使用:支持XML配置、注解(如@Value)、编程式调用;
  3. 丰富的语法:涵盖字面量、运算符、类型转换、集合操作、Bean引用等;
  4. 与Spring无缝集成:可直接访问Spring容器中的Bean、环境变量、系统属性等。

二、基本语法与常用场景

1. 字面量表达式

支持字符串、数字、布尔、null等基础类型的直接表达:

// 编程式调用示例(核心类:ExpressionParser、SpelExpressionParser、EvaluationContext)ExpressionParserparser=newSpelExpressionParser();// 字符串(单引号包裹)Expressionexp1=parser.parseExpression("'Hello SpEL'");Stringstr=(String)exp1.getValue();// 结果:Hello SpEL// 数字Expressionexp2=parser.parseExpression("100 + 200 * 2");intnum=(Integer)exp2.getValue();// 结果:500// 布尔Expressionexp3=parser.parseExpression("true && false");booleanbool=(Boolean)exp3.getValue();// 结果:false// nullExpressionexp4=parser.parseExpression("null");ObjectnullObj=exp4.getValue();// 结果:null

2. 属性与方法调用

通过.访问对象属性/方法,支持嵌套访问:

// 定义测试对象classUser{privateStringname;privateList<String>hobbies;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicList<String>getHobbies(){returnhobbies;}publicvoidsetHobbies(List<String>hobbies){this.hobbies=hobbies;}publicStringsayHello(Stringmsg){return"Hello: "+msg;}}// 初始化上下文Useruser=newUser();user.setName("张三");user.setHobbies(Arrays.asList("篮球","读书"));EvaluationContextcontext=newStandardEvaluationContext(user);// 访问属性Stringname=(String)parser.parseExpression("name").getValue(context);// 张三// 调用方法(带参数)Stringhello=(String)parser.parseExpression("sayHello('SpEL')").getValue(context);// Hello: SpEL// 嵌套访问(集合属性)Stringhobby=(String)parser.parseExpression("hobbies[0]").getValue(context);// 篮球

3. 运算符

支持算术、逻辑、关系、赋值、三元运算符等:

类型运算符示例说明
算术10 + 23 * 410 % 3加减乘除、取模
逻辑`true
关系5 > 3'abc' == 'abc'大于、等于、不等于等
赋值name = '李四'为属性赋值
三元运算name == '张三' ? '是' : '否'条件判断
Elvis运算符name ?: '默认值'简化空判断(name为空则返回默认值)

示例:

// 三元运算Stringresult=(String)parser.parseExpression("name == '张三' ? '管理员' : '普通用户'").getValue(context);// 管理员// Elvis运算符(空保护)parser.parseExpression("name = null").getValue(context);StringdefaultName=(String)parser.parseExpression("name ?: '未知用户'").getValue(context);// 未知用户

4. 集合操作

支持访问集合元素、筛选、投影等:

// 1. 访问List/MapList<Integer>nums=Arrays.asList(1,2,3,4);EvaluationContextlistContext=newStandardEvaluationContext(nums);intfirst=(Integer)parser.parseExpression("[0]").getValue(listContext);// 1Map<String,Integer>map=newHashMap<>();map.put("a",10);map.put("b",20);EvaluationContextmapContext=newStandardEvaluationContext(map);intval=(Integer)parser.parseExpression("['b']").getValue(mapContext);// 20// 2. 集合筛选(.?[表达式])List<Integer>evenNums=(List<Integer>)parser.parseExpression(".?[#this % 2 == 0]").getValue(listContext);// [2,4]// 3. 集合投影(.![表达式])List<String>strNums=(List<String>)parser.parseExpression(".![#this + '号']").getValue(listContext);// [1号,2号,3号,4号]

5. Spring容器集成

(1)引用Spring Bean(@符号)

在Spring环境中,可直接引用容器中的Bean:

// 假设容器中有一个名为"userService"的Bean@Value("#{userService}")privateUserServiceuserService;// 调用Bean的方法@Value("#{userService.getUserName(1)}")privateStringuserName;
(2)访问环境变量/系统属性
// 系统属性(systemProperties)@Value("#{systemProperties['os.name']}")privateStringosName;// 例如:Windows 10// 环境变量(environment)@Value("#{environment['JAVA_HOME']}")privateStringjavaHome;// Spring配置属性(application.properties)@Value("#{my.properties['app.name']}")privateStringappName;

6. 注解中的常用场景

(1)@Value注解(区别:${}是占位符,#{}是SpEL)
// 基础值@Value("#{100 * 2}")privateintnum;// 200// 空判断@Value("#{user.name ?: '默认名称'}")privateStringuserName;// 集合@Value("#{T(java.util.Arrays).asList('a','b','c')}")privateList<String>letters;
(2)@PreAuthorize(Spring Security权限控制)
// 权限表达式(判断用户是否有指定角色)@PreAuthorize("#userId == authentication.principal.id or hasRole('ADMIN')")publicvoiddeleteUser(LonguserId){// 业务逻辑}

三、编程式使用SpEL的完整示例

importorg.springframework.expression.Expression;importorg.springframework.expression.ExpressionParser;importorg.springframework.expression.spel.standard.SpelExpressionParser;importorg.springframework.expression.spel.support.StandardEvaluationContext;publicclassSpELDemo{publicstaticvoidmain(String[]args){// 1. 创建表达式解析器ExpressionParserparser=newSpelExpressionParser();// 2. 定义上下文(绑定对象)Useruser=newUser();user.setName("李四");user.setAge(25);StandardEvaluationContextcontext=newStandardEvaluationContext(user);// 3. 解析表达式// 访问属性Stringname=(String)parser.parseExpression("name").getValue(context);System.out.println("姓名:"+name);// 李四// 运算 + 赋值parser.parseExpression("age = age + 1").getValue(context);intage=(Integer)parser.parseExpression("age").getValue(context);System.out.println("年龄:"+age);// 26// 方法调用Stringgreet=(String)parser.parseExpression("sayHello('SpEL')").getValue(context);System.out.println(greet);// Hello: SpEL}staticclassUser{privateStringname;privateintage;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}publicStringsayHello(Stringmsg){return"Hello: "+msg;}}}

四、注意事项

  1. 性能:SpEL运行时解析,高频调用场景需缓存解析后的Expression对象;
  2. 安全:避免解析用户输入的表达式(防止注入攻击);
  3. 区别${}#{}
    • ${}:Spring占位符,仅做字符串替换(先解析);
    • #{}:SpEL表达式,支持动态求值(后解析);
    • 混合使用:@Value("${app.name:#{systemProperties['user.name']}}")(占位符默认值用SpEL);
  4. 类型转换:SpEL内置类型转换器,可自定义TypeConverter扩展。

五、核心API总结

类/接口作用
ExpressionParser表达式解析器(核心接口)
SpelExpressionParserExpressionParser的默认实现
EvaluationContext表达式求值上下文(绑定变量、Bean等)
StandardEvaluationContextEvaluationContext的默认实现
Expression解析后的表达式对象(可多次求值)

SpEL是Spring生态中灵活的动态表达式工具,核心场景包括配置注入、权限控制、动态规则判断等,掌握其语法可大幅提升Spring开发的灵活性。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/26 10:39:36

LobeChat能否实现多人协同编辑?共享会话功能设想

LobeChat能否实现多人协同编辑&#xff1f;共享会话功能设想 在远程办公常态化、AI助手深度融入工作流的今天&#xff0c;一个看似简单却日益凸显的问题浮出水面&#xff1a;我们能否像协作编辑一份文档那样&#xff0c;多人实时共用同一个AI对话&#xff1f; 想象这样一个场…

作者头像 李华
网站建设 2026/8/27 6:26:57

基于单片机的智能温控风扇系统设计(温度+风速调节)【附代码】

&#x1f4c8; 算法与建模 | 专注PLC、单片机毕业设计 ✨ 擅长数据搜集与处理、建模仿真、程序设计、仿真代码、论文写作与指导&#xff0c;毕业论文、期刊论文经验交流。✅ 专业定制毕业设计✅ 具体问题可以私信或查看文章底部二维码本系统的核心设计内容在于构建一个以单片机…

作者头像 李华
网站建设 2026/8/26 22:12:41

Python中配置TensorFlow-GPU的完整方法

Python中配置TensorFlow-GPU的完整方法 在深度学习项目开发中&#xff0c;模型训练动辄需要数小时甚至数天&#xff0c;而能否充分利用GPU资源&#xff0c;往往决定了整个研发流程的效率。如果你还在用CPU跑ResNet或Transformer&#xff0c;那可能连一个epoch都坚持不下来就放…

作者头像 李华
网站建设 2026/8/27 2:32:33

基于单片机的智能晾衣架控制系统设计【附代码】

&#x1f4c8; 算法与建模 | 专注PLC、单片机毕业设计 ✨ 擅长数据搜集与处理、建模仿真、程序设计、仿真代码、论文写作与指导&#xff0c;毕业论文、期刊论文经验交流。✅ 专业定制毕业设计✅ 具体问题可以私信或查看文章底部二维码在智能晾衣架控制系统的核心控制单元与驱动…

作者头像 李华
网站建设 2026/8/24 10:08:32

SP40P65NJ:一款高性能40V P沟道MOSFET深度解析

在电源管理与DC-DC转换器设计中&#xff0c;MOSFET的选择直接影响系统的效率、可靠性与成本。今天我们将推出的一款40V P沟道MOSFET——SP40P65NJ&#xff0c;结合其官方规格书&#xff0c;从关键参数、性能特点到封装信息进行全面梳理。一、核心规格摘要参数典型值条件漏源击穿…

作者头像 李华
网站建设 2026/8/25 15:49:15

基于单片机的智能卧室助眠灯光系统设计【附代码】

&#x1f4c8; 算法与建模 | 专注PLC、单片机毕业设计 ✨ 擅长数据搜集与处理、建模仿真、程序设计、仿真代码、论文写作与指导&#xff0c;毕业论文、期刊论文经验交流。✅ 专业定制毕业设计✅ 具体问题可以私信或查看文章底部二维码智能卧室助眠灯光系统的设计核心在于通过单…

作者头像 李华