【SpringBoot3】SpEL表达式详细使用说明

一、介绍

SpEL(Spring Expression Language)是Spring框架提供的一种功能强大的表达式语言,用于在运行时查询和操作对象。

主要特点和用途包括:

  1. 简洁性:SpEL表达式使用简洁的语法,使得在Spring配置和代码中能够更简洁地表达复杂的逻辑。
  2. 动态性:SpEL表达式能够在运行时动态地解析和执行,从而提供了更大的灵活性。
  3. 强大的功能:SpEL表达式支持各种功能,如方法调用、字符串模板、集合操作、逻辑运算等,使得在Spring配置和代码中能够完成复杂的逻辑处理。

SpEL表达式的语法以“#{}”为标记,可以在Spring配置文件的XML中、注解中以及Java代码中使用。

在XML中,可以在属性值中使用SpEL表达式,例如:

<bean id="person" class="com.example.Person"><property name="name" value="#{'John Doe'}"/><property name="age" value="#{30}"/>
</bean>

在注解中,可以使用@Value注解来注入SpEL表达式的值,例如:

@Value("#{'Hello World'}")
private String message;

在Java代码中,可以创建Expression对象来执行SpEL表达式,例如:

User user = new User("张三");
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello ' + #user.name");
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("user", user);
String name = (String) exp.getValue(context);
System.out.println(name);

除了基本的表达式功能外,SpEL还提供了对集合、数组、Map等复杂数据结构的操作,以及对Spring容器中的Bean的引用和操作。这使得在Spring配置和代码中能够更方便地处理复杂的数据结构和业务逻辑。

SpEL表达式的优势

SpEL表达式(Spring Expression Language)的优势主要体现在以下几个方面:

  1. 动态性:SpEL表达式在运行时执行,可以根据应用程序的状态和环境动态地计算值。这种动态性使得SpEL能够适应各种复杂的场景,并提供更大的灵活性。

  2. 简洁性:SpEL表达式提供了一种简洁、紧凑的语法,用于表示和操作对象。与传统的XML配置相比,SpEL表达式可以更简洁地表达相同的逻辑,从而减少了配置的复杂性。

  3. 强大的功能:SpEL表达式支持丰富的功能,包括方法调用、字符串模板、集合操作、逻辑运算等。这使得在Spring配置和代码中能够更轻松地处理复杂的逻辑和数据结构。

  4. 易于集成:SpEL表达式与Spring框架紧密集成,可以方便地与其他Spring特性结合使用,如依赖注入、AOP(面向切面编程)、事务管理等。这使得在Spring应用程序中能够更轻松地实现各种功能。

  5. 灵活性:SpEL表达式可以在多个地方使用,包括XML配置文件、注解和Java代码中。这种灵活性使得SpEL能够适应不同的开发需求和场景。

  6. 可扩展性:SpEL表达式的设计是可扩展的,可以通过自定义函数和操作符来扩展其功能。这使得开发者可以根据自己的需求定制SpEL表达式的行为。

二、语法

SpEL(Spring Expression Language)的语法包括以下几种基本表达式:

  1. 字面量表达式

    • 支持的字面量类型包括:字符串、数字(int、long、float、double)、布尔类型、null类型。
    • 示例:'Hello World', 42, 3.14, true, null
  2. 算数运算表达式

    • 支持的运算符包括:加(+)、减(-)、乘(*)、除(/)、求余(%)、幂(^)。
    • 还提供了求余(MOD)和除(DIV)两个额外运算符,它们与“%”和“/”是等价的,且不区分大小写。
    • 示例:4 + 5, 10 - 3, 2 * 7, 14 / 2, 21 % 3, 2 ^ 3
  3. 关系表达式

    • 支持的关系运算符包括:等于(==)、不等于(!=)、大于(>)、大于等于(>=)、小于(<)、小于等于(<=)。
    • 示例:4 > 3, 2 != 5, 10 >= 10, 1 <= 2
  4. 逻辑表达式

    • 支持的逻辑运算符包括:AND(&&)、OR(||)、NOT(!)。
    • 示例:(a > b) && (c < d), (x == y) || (z != w), !isTrue
  5. 正则表达式

    • 可以使用正则表达式进行字符串匹配。
    • 示例:'abc'.matches('.b.') 将返回 true
  6. 集合操作

    • 支持集合操作,如选择(?)、投影(![])、集合的大小(size)、是否包含(in)等。
    • 示例:list.?[#this > 3], list.[#this.name], list.size(), 'item' in list
  7. 方法调用

    • 可以调用对象的方法。
    • 示例:'Hello World'.toUpperCase(), someObject.someMethod()
  8. 变量引用

    • 可以引用在表达式上下文中定义的变量。
    • 示例:#variableName
  9. 类型运算符

    • 提供了一个特殊的运算符 T(),用于指定一个类型字面量。
    • 示例:T(java.lang.String).class 将返回 java.lang.String.class
  10. 三元运算符

    • 类似于其他编程语言中的条件运算符,格式为 condition ? valueIfTrue : valueIfFalse
    • 示例:(a > b) ? a : b
  11. 区间运算符

    • 使用 between 关键字来表示一个值是否在指定的区间内。
    • 示例:1 between 2 and 3 将返回 false,而 2 between 2 and 3 将返回 true
  12. 索引器

    • 可以使用方括号 [] 来访问数组、列表、映射(如Map)的元素。
    • 示例:myList[0], myMap['key']
  13. 函数调用

    • 可以直接调用静态方法或实例方法。
    • 示例:T(java.lang.Math).max(a, b), myObject.myMethod()
  14. 安全导航运算符

    • 使用 ?. 来进行安全的导航访问,如果左侧对象为 null 则不会抛出异常,而是返回 null
    • 示例:user?.address?.city

这些表达式可以单独使用,也可以组合起来创建更复杂的表达式。SpEL 提供了强大而灵活的表达式语言,可以在运行时动态地评估和计算表达式。

三、应用场景

SpEL表达式在Spring框架中有广泛的应用场景,以下是其中一些常见的使用场景:

  1. XML配置中的属性值:在Spring的XML配置文件中,可以使用SpEL表达式来设置bean的属性值。例如,你可以使用SpEL表达式来引用其他bean、计算属性值或执行简单的逻辑操作。

  2. 注解中的值:在Spring的注解中,你也可以使用SpEL表达式来注入值。例如,在@Value注解中,你可以使用SpEL表达式来指定一个属性的值。

  3. 方法参数:在调用方法时,可以使用SpEL表达式来动态地设置方法的参数值。这可以在配置文件中或者在Java代码中实现。

  4. 集合操作:SpEL表达式提供了对集合的支持,你可以使用它来操作集合,如遍历集合、过滤元素、投影等。

  5. 条件判断:SpEL表达式支持条件运算,你可以在配置或代码中使用它来进行条件判断,根据条件的结果来设置属性值或执行不同的逻辑。

  6. 属性值的动态计算:有时你可能需要根据其他属性值或环境变量来动态计算某个属性的值。SpEL表达式可以帮助你实现这一点。

  7. 简化配置:通过使用SpEL表达式,你可以简化Spring的配置。例如,你可以使用它来避免冗长的XML配置,或者在Java配置中更简洁地表达逻辑。

  8. 与Spring其他特性结合使用:SpEL表达式可以与其他Spring特性结合使用,如AOP(面向切面编程)、事务管理等。你可以使用SpEL表达式来定义切点表达式、事务属性等。

需要注意的是,虽然SpEL表达式功能强大且灵活,但并不意味着它应该在所有场景下都被使用。在决定使用SpEL表达式之前,应该仔细考虑其是否适合当前的需求,并权衡其带来的好处和可能的复杂性。

四、符号(#、$、@)各有什么不同

1、#开头(#{}

#{} 用于定义 SpEL 表达式。在这个上下文中,你可以执行方法调用、访问字段、执行算术运算等。#{} 内的表达式会被计算,并且其结果会被返回。这通常用于动态地计算值或执行复杂的逻辑。

示例:

#{systemProperties['os.name']} // 访问系统属性
#{myBean.myMethod()} // 调用Bean的方法
#{[1, 2, 3]} // 内联列表
#{{'key':'value'}} // 内联映射

#{} 内部,你还可以访问 Spring 提供的内置变量和方法,例如 #root#this#parameters 等。

2、@开头(@

@符号在SpEL中用于引用命名Bean。这是Spring EL的特定功能,它允许你直接引用Spring容器中的Bean,而不需要通过ApplicationContext来获取它们。

示例:

@myBean // 引用名为'myBean'的Bean

请注意,当你使用@来引用Bean时,实际上你是在告诉SpEL引擎从Spring的ApplicationContext中查找并注入这个Bean。

3、$ 开头(${}

在 SpEL 中, ∗ ∗ 通常用于直接引用变量。这通常在从外部源(如配置文件)注入变量时使用。在 S p r i n g 的 ‘ @ V a l u e ‘ 注解中,你可以使用 ∗ ∗ ** 通常用于直接引用变量。这通常在从外部源(如配置文件)注入变量时使用。在 Spring 的 `@Value` 注解中,你可以使用 ** 通常用于直接引用变量。这通常在从外部源(如配置文件)注入变量时使用。在Spring‘@Value注解中,你可以使用 来引用配置文件中定义的属性。

示例:

@Value("${my.property}")
private String myProperty;

在这个例子中,${my.property} 告诉 Spring 从配置文件中查找 my.property 的值,并将其注入到 myProperty 字段中。

```
my.property=Hello, world!
```

总结

  • #{} 用于编写 SpEL 表达式,执行方法调用、计算值等。
  • $ 通常用于引用配置文件中定义的属性,在 @Value 注解等场景中使用。
  • @用于直接引用Spring容器中的Bean。

需要注意的是, ∗ ∗ 在 S p E L 表达式中并不总是用于引用变量。在某些情况下, ∗ ∗ ** 在 SpEL 表达式中并不总是用于引用变量。在某些情况下,** SpEL表达式中并不总是用于引用变量。在某些情况下, 也可以用于表示字面量或特定的 SpEL 功能。但是,在大多数情况下,$ 在 SpEL 中与变量引用相关,而 # 则用于定义表达式。

五、Spring中@Value() 的用法

@Value 是Spring框架中的一个注解,它主要用于从配置文件中注入属性值到Bean的字段、方法参数或构造函数中。以下是 @Value 注解的一些常见用法:

1、直接注入简单类型的值

你可以使用 @Value 注解直接将配置文件中定义的属性值注入到Bean的字段中。例如:

   @Value("Hello World")private String greeting;

在这个例子中,greeting 字段将被赋值为 “Hello World”。

2、注入来自配置文件的值

你可以使用占位符语法 ${...} 来引用配置文件(如 application.propertiesapplication.yml)中的值。例如:

@Value("${app.name}")
private String appName;

在这个例子中,appName 字段将被赋值为 app.name 在配置文件中定义的值。

3、注入系统属性

使用 #{...} 语法,你可以注入系统属性。例如:

@Value("#{systemProperties['os.name']}")
private String osName;

这里,osName 字段将被赋值为系统的 os.name 属性。

4、注入环境变量

同样使用 #{...} 语法,你可以注入环境变量。例如:

@Value("#{environment['MY_ENV_VAR']}")
private String myEnvVar;

这里,myEnvVar 字段将被赋值为 MY_ENV_VAR 环境变量的值。

5、注入表达式的结果

你可以在 #{...} 中使用SpEL表达式来计算值。例如:

@Value("#{10 * 2}")
private int result;

这里,result 字段将被赋值为 10 * 2 的计算结果,即 20。

6、注入数组、集合和Map

你可以使用 @Value 注解来注入数组、集合和Map。例如:

@Value("#{'red', 'green', 'blue'}")
private List<String> colors;@Value("#{{'key1':'value1', 'key2':'value2'}}")
private Map<String, String> configMap;

在这个例子中,colors 列表将被赋值为包含 'red', 'green', 和 'blue' 的列表,configMap 将被赋值为包含 'key1': 'value1''key2': 'value2' 的映射。

7、使用默认值

当配置文件中没有定义某个属性时,你可以为 @Value 注解提供一个默认值。例如:

@Value("${app.version:1.0.0}")
private String appVersion;

如果 app.version 没有在配置文件中定义,appVersion 将被赋值为默认值 “1.0.0”。

请注意,为了使 @Value 注解能够工作,你的类需要被Spring容器管理,即它应该是一个Bean(可以通过
@Component@Service@Repository@Controller
等注解来标识)。此外,如果你在静态变量上使用
@Value,那么它可能无法正常工作,因为静态变量在类加载时初始化,而这时Spring可能还没有解析 @Value
注解。为了避免这种情况,你应该在实例变量上使用 @Value,并通过setter方法或构造函数注入来设置静态变量的值。

六、使用示例

1、简单表达式

ExpressionParser parser = new SpelExpressionParser();
// 简单的字符串表达式
Expression exp1 = parser.parseExpression("'Hello World'");
String message = (String) exp1.getValue();
System.out.println(message); // 输出: Hello World// 算术表达式
Expression exp2 = parser.parseExpression("10 * 2");
int result = (int) exp2.getValue();
System.out.println(result); // 输出: 20

2、从对象中取值

ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();Expression exp1 = parser.parseExpression("#user.name");
context.setVariable("user", new User("Alice"));
String userName = (String) exp1.getValue(context);
System.out.println(userName); // 输出: AliceList<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 过滤出长度大于4的名字
Expression exp3 = parser.parseExpression("#names.?[#this.length > 4]");
context.setVariable("names", names);
List<String> filteredNames = (List<String>) exp3.getValue(context);
System.out.println(filteredNames); // 输出: [Charlie]
public void readBeanProperty() {ExpressionParser parser = new SpelExpressionParser();Expression exp = parser.parseExpression("name");// 获取属性的值Object propertyValue = exp.getValue(new User("张三"));// 输出属性的值System.out.println("The value of myProperty is: " + propertyValue);
}

3、读取系统环境变量

public void systemProperties() {Properties properties = System.getProperties();for (Map.Entry<Object, Object> entry : properties.entrySet()) {System.out.println(entry.getKey() + "===" + entry.getValue());}
}
// 输出 zh
@Value("#{systemProperties['user.language']}")

参考

  • https://docs.spring.io/spring-framework/reference/core/expressions.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/704065.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端取图片相同颜色作为遮罩或者背景

需求 遮罩层取图片相同/相似的颜色作为遮罩 效果 做法 npm库 grade.js 所提供图像中前 2 个主色生成的互补渐变https://github.com/benhowdle89/grade COLOR THIEF 只需使用Javascript即可从图像中获取调色板。 https://github.com/lokesh/color-thief https://lokeshd…

DNS的意义,DNS不可用该怎么办

DNS是域名系统&#xff0c;它负责将我们输入的网址(如www.baidu.com)转换成计算机可以理解的IP地址(如127.0.0.1)。DNS设置的好坏&#xff0c;直接影响到我们的上网速度和体验。 一、DNS的重要性 在访问一个网站时&#xff0c;首先需要通过DNS将域名解析为对应的IP地址。如果DN…

5.24 BCC工具之funccount.py解读

一,工具简介 funccount工具可以追踪与指定模式匹配的函数、追踪点或USDT探针,并会在追踪过程中打印它们的计数摘要。 二,代码示例 #!/usr/bin/env pythonfrom __future__ import print_function from bcc import ArgString, BPF, USDT from time import sleep, strftime …

【深度学习笔记】4_2-3 模型参数的访问、初始化和共享

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 4.2 模型参数的访问、初始化和共享 在3.3节&#xff08;线性回归的简洁实现&#xff09;中&#xff0c;我们通过init模块来初始化模型…

AIGC专栏9——Scalable Diffusion Models with Transformers (DiT)结构解析

AIGC专栏9——Scalable Diffusion Models with Transformers &#xff08;DiT&#xff09;结构解析 学习前言源码下载地址网络构建一、什么是Diffusion Transformer (DiT)二、DiT的组成三、生成流程1、采样流程a、生成初始噪声b、对噪声进行N次采样c、单次采样解析I、预测噪声I…

kitti数据显示

画出track_id publish_utils.py中 def publish_3dbox(box3d_pub, corners_3d_velos, types, track_ids):marker_array MarkerArray()for i, corners_3d_velo in enumerate(corners_3d_velos):marker Marker()marker.header.frame_id FRAME_IDmarker.header.stamp rospy.T…

Pytorch训练RCAN QAT超分模型

Pytorch训练RCAN QAT超分模型 版本信息测试步骤准备数据集创建容器生成文件列表创建文件列表的代码执行脚本,生成文件列表训练RCAN模型准备工作修改开源代码编写训练代码执行训练脚本可视化本文以RCAN超分模型为例,演示了QAT的训练过程,步骤如下: 先训练FP32模型再加载FP32训练…

量子计算学习经验

推荐B站冉仕举老师视频&#xff08;老师讲的详细又耐心&#xff0c;张量网络做量子计算&#xff0c;不过有些基础概念都是通用的&#xff09; StringCNU的个人空间-StringCNU个人主页-哔哩哔哩视频 2《量子计算与量子信息》是经典的教材书的&#xff0c;但是大部分同学第一次看…

【随笔】固态硬盘数据删除无法恢复(开启TRIM),注意数据备份

文章目录 一、序二、机械硬盘和固态硬盘的物理结构与工作原理2.1 机械硬盘2.11 基本结构2.12 工作原理 2.2 固态硬盘2.21 基本结构2.22 工作原理 三、机械硬盘和固态硬盘的垃圾回收机制3.1 机械硬盘GC3.2 固态硬盘GC3.3 TRIM指令开启和关闭 四、做好数据备份 一、序 周末电脑突…

数据库设计过程中的各种模式

在数据库设计过程中&#xff0c;有几种常见的模式&#xff0c;它们有助于组织和管理数据。以下是这几种模式的简介&#xff1a; 主扩展模式&#xff08;也称为主从模式&#xff09;&#xff1a;这种模式适用于多个表具有相似结构的情况。这些表共享某些基本属性&#xff08;也…

备战蓝桥之二分

二分题目&#xff1a; B3880 [信息与未来 2015] 买木头 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.security.PublicKey; impor…

【Qt学习】QLineEdit 控件 属性与实例(登录界面,验证密码,正则表达式)

文章目录 1. 介绍2. 实例使用2.1 登录界面2.2 对比两次密码是否相同2.3 通过按钮显示当前输入的密码&#xff08;并对2.2进行优化&#xff09;2.4 结语 3. 正则表达式3.1 QRegExp3.2 验证输入内容 4. 资源代码 1. 介绍 关于 QLineEdit 的详细介绍&#xff0c;可以去查阅官方文…

[计算机网络]--IP协议

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、IP协议…

202432读书笔记|《泰戈尔的诗》——什么事让你大笑,我生命的小蓓蕾

202432读书笔记|《泰戈尔的诗》——什么事让你大笑&#xff0c;我生命的小蓓蕾 《泰戈尔写给孩子的诗&#xff08;中英双语版&#xff09;》作者拉宾德拉纳特泰戈尔文 张王哲图&#xff0c;图文并茂的一本书&#xff0c;文字与图画都很美&#xff0c;相得益彰&#xff01;很值得…

【Memory协议栈】EEPROM Abstraction模块详细介绍

目录 前言 正文 1.功能简介 2.关键概念 3.功能详解 3.1 Addressing scheme and segmentation 3.2 Address calculation 3.3 Limitation of erase / write cycles 3.4 Handling of “immediate” data 3.5 Managing block consistency information 4.关键API定义 4.…

学习磁盘管理

文章目录 一、磁盘接口类型二、磁盘设备的命名三、fdisk分区四、自动挂载五、扩容swap六、GPT分区七、逻辑卷管理八、磁盘配额九、RAID十、软硬链接 一、磁盘接口类型 IDE、SATA、SCSI、SAS、FC&#xff08;光纤通道&#xff09; IDE, 该接口是并口。SATA, 该接口是串口。SCS…

Linux笔记--文件内容的查阅与统计

一、文件内容的查阅 1.cat指令 concatenate&#xff0c;连接文件并打印到标准输出设备上(查看文件) &#xff08;1&#xff09; #cat文件的路径 常用选项: -n列出行号 &#xff08;2&#xff09;#tac 含义:倒序显示&#xff08;应用:查看日志) 2. head指令 查看一个文件的前n行…

golang学习2,golang开发配置国内镜像

go env -w GO111MODULEon go env -w GOPROXYhttps://goproxy.cn,direct

npm已经配置淘宝源仍然无法使用

使用npm命令安装Taro框架的时候&#xff0c;尽管已经设置淘宝源但是仍然无法下载&#xff0c;提示错误 >npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED npm ERR! request to https://registry.npm.taobao.org/cnpm failed, reason: certificate h…

K8S部署Java项目(Gitlab CI/CD自动化部署终极版)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…