当前位置: 首页 > ds >正文

Spring中的SpEL是什么

一句话:SpEL(Spring Expression Language)是 Spring 自带的“运行时表达式语言”,用来在 XML、注解、代码 里动态取值、运算、调用方法,功能对标 OGNL / EL,但语法更简洁、与 Spring 容器深度集成。


1. 能做什么(直接举例)

场景示例结果
注入配置文件里的值@Value("#{systemProperties['user.region']}")取 JVM 启动参数
引用其他 Bean 的属性@Value("#{orderService.nextOrderId}")实时拿到 orderService 的字段
调用静态方法@Value("#{T(java.lang.Math).random()}")0~1 随机数
集合过滤 / 投影@Value("#{users.?[age > 18]}")返回成年用户列表
条件判断@Value("#{profile == 'prod' ? 8080 : 9000}")动态端口

2. 语法速记(30 秒写完)

#{ }            表达式定界符
T(全限定类)      访问静态类/方法
bean.property   访问 Bean 属性
bean.method()   调用 Bean 方法
list[0]         索引
map['key']      Map 取值
.?[ ] .![ ]     过滤 / 投影

3. 运行原理(一句话背)

SpEL 被解析成 AST → EvaluationContext → 反射执行,Spring 默认把容器注册成 BeanFactoryResolver,所以表达式里可以直接写 Bean 名。

4. 常见坑

  1. 表达式拼错启动不报错
    @Value("#{nosuchBean.xxx}") 只有在第一次注入时才会抛 SpelEvaluationException,属于“运行时异常”,单元测试容易漏掉。

  2. 类型自动拆装箱失败
    @Value("#{1}") 注入到 int 可以,注入到 Integer 没问题;但注入到 boolean 会抛 ClassCastException,需要显式 #{1 != 0}

  3. 与占位符 ${} 混用

    • ${} 只能读 属性源(application.yml、环境变量)。
    • #{} 可以读 Bean、系统属性、运算
      错误示例:@Value("${systemProperties['user.region']}") → 应改为 #{}
  4. 集合投影后类型丢失
    #{users.![name]} 返回 List<String>,但注入到 List<User> 会报类型不匹配,需要显式强转或泛型擦除处理。

  5. 性能陷阱
    表达式每次注入都会重新解析;在 循环或高并发 场景,建议把结果缓存到局部变量,或使用 Expression 预编译:

    Expression exp = parser.parseExpression("price * discount");
    

5. 实战 3 连击

  1. 动态路由数据源

    @Bean
    @Scope("prototype")
    public DataSource dataSource(@Value("#{dsProps.urls[T(ThreadLocalRandom).current().nextInt(dsProps.urls.size())]}") String url) {return new DriverManagerDataSource(url, user, pwd);
    }
    
  2. AOP 切点里用 SpEL

    @Around("@annotation(rateLimit) && args(id)")
    public Object limit(ProceedingJoinPoint pjp, RateLimit rateLimit, Long id) {String key = parser.parseExpression(rateLimit.key()).getValue(context, id, String.class);...
    }
    
  3. Thymeleaf 模板

    <span th:text="${@userService.findById(#vars.userId).name}"></span>
    

6. 一句话总结

SpEL 就是 Spring 的“运行时脚本”,能在注解、XML、模板里直接读写 Bean、环境变量、集合、静态方法,语法简洁、功能强大,但要警惕运行时异常和性能开销。

http://www.xdnf.cn/news/15831.html

相关文章:

  • Springboot3整合Elasticsearch8(elasticsearch-java)
  • [2025CVPR-目标检测方向]FSHNet:一种用于3D物体检测的全稀疏混合网络。
  • Hive数据仓库工具
  • 什么是高光谱相机,它与数码相机有什么区别?
  • 相机光学(五十)——Depth AF
  • RTKLIB读取星历文件,观测数据
  • 解决Flutter运行android提示Deprecated imperative apply of Flutter‘s Gradle plugins
  • 电解电容串联均衡电阻计算
  • 模板初阶和C++内存管理
  • 功能安全之BIST的基本原理
  • 第7天 | openGauss中一个数据库中可以创建多个模式
  • 6月零售数据超预期引发市场波动:基于AI多因子模型的黄金价格解析
  • Axios泛型参数解析与使用指南
  • 当系统盘快满时,可以删除哪些数据
  • 排序【各种题型+对应LeetCode习题练习】
  • 如何阅读Spring源码
  • 【LVGL】Linux LVGL程序几十分钟后UI卡死
  • effective python 条款11 学会对序列做切片
  • Onload 用户指南 (UG1586)-笔记
  • 【机器学习】安装Jupyter及基本操作
  • 内存泄漏系列专题分析之二十九:高通相机CamX--Android通用GPU内存分配和释放原理
  • 虚拟商品自动化实践:闲鱼订单防漏发与模板化管理的技术解析
  • JVM常用运行时参数说明
  • 【C# in .NET】17. 探秘类成员-构造函数与析构函数:对象生命周期管理
  • [3-02-01].第01章:框架概述 - Spring生态
  • 基于Spring Boot的农村农产品销售系统设计与实现
  • 【Python】DRF核心组件详解:Mixin与Generic视图
  • ARINC818航空总线机载视频处理系统设计
  • 第二篇 html5和css3开发基础与应用
  • 28、鸿蒙Harmony Next开发:不依赖UI组件的全局气泡提示 (openPopup)和不依赖UI组件的全局菜单 (openMenu)、Toast