Spring Expression Language (SpEL)

?Spring 表達語言(SpEL),支持在運行時查詢和操作對象圖,可以用于數據綁定、屬性訪問、方法調用等。使用SpEL可以簡化代碼并提高應用程序的可維護性。

1 概覽

SpelExpressionParser是SpEL的一個核心組件,負責解析和編譯SpEL表達式。Expression 是根據上下文計算的表達式,封裝了之前分析的表達式的詳細信息,為表達式計算提供接口。

public static void main(String[] args) {SpelExpressionParser parser = new SpelExpressionParser();String str1 = parser.parseExpression("'hello'.concat(' SpEL')").getValue(String.class); // hello SpELInteger sum = parser.parseExpression("1 + 99").getValue(Integer.class); // 100}

1.1 EvaluationContext

是SpEL中用于計算表達式的上下文,提供了一個環境,使得SpEL表達式可以訪問和操作其中的變量和對象。(在Spring上下文中,通常不要手動創建EvaluationContext,容器會自動創建并管理)

包含多個對象

可以是任何Java對象,供表達式引用和操作。

根對象

只有一個根對象,是上下文中的核心對象,其他對象可以通過根對象進行訪問。

變量解析

可以在其中設置和獲取變量的值,會根據其中的值來解析和執行表達式。

類型轉換

在執行SpEL表達式時,可以將一種類型的值轉換為另一種類型。(通過ConversionService 來完成轉換)

反射機制

通常使用反射機制來操作對象,可以動態地訪問和調用對象的屬性和方法。

性能優化

會在其內部緩存反射信息。

表 EvaluationContext 提供的功能

其有兩個實現:

StandardEvaluationContext:提供了全套的SpEL語言功能和配置選項。

SimpleEvaluationContext:僅支持SpEL語法的子集,不包括Java類型引用、構造函數和bean引用。會更安全。

public static void testContext() {User user = new User("hmf");StandardEvaluationContext context = new StandardEvaluationContext(user);List<String> strList = new ArrayList<>();strList.add("hello");strList.add("java");context.setVariable("list",strList);SpelExpressionParser parser = new SpelExpressionParser();String username = parser.parseExpression("username").getValue(context, String.class);System.out.println(parser.parseExpression("#list").getValue(context)); // [hello, java]System.out.println(username); // hmf}

1.2 編譯器

SpEL 表達式通常在運行期間通過解釋器進行進行執行,但是這樣性能不是很好。SpEL 編譯器是對表達式進行編譯(在運行前或運行中),將表達式生成一個Java類。(注意:編譯器適合表達式中的類型保持穩定的情況下使用)

OFF

默認模式,編譯器被關閉。

IMMEDIDATE

表達式會盡快被編譯,通常發生在第一次解釋評估之后。

MIXED

表達式會在解釋模式和編譯模式之間靜默轉換。一開始,表達式會進行解釋執行,經過一定數量的解釋執行后,它們會切換到編譯模式。如果編譯模式出現問題(例如類型更改),則表達式會自動切回解釋模式,一段時間后,可能會編譯成新的格式并切回到它。

表 SpEL編譯器的三種模式

注意:SpEL 要在運行時才能發現錯誤,編譯階段不能發現錯誤。

1.2.1 MIXED模式的不足

1)前期MIXED會解釋執行,效率可能會比編譯執行慢。

2)MIXED 可能會自動切回解釋模式,這樣雖能保證表達式的可用性,但也導致了性能上的不穩定(每次切換到解釋模式時,都需要重新進行解釋執行,這可能會比編譯執行更耗時)。

1.2.2 編譯模式下的限制

以下情況的表達式不能在編譯模式下執行:

  1. 涉及賦值。
  2. 依賴轉換服務的表達式。
  3. 使用自定義解析器或訪問器。
  4. 使用選擇或投影表達式(例如#{}、![])。

1.3 在Bean定義中使用

在IoC容器中,定義Bean時,可以使用SpEL 表達式來給屬性賦值。語法為:#{表達式}。

注解模式:

@Value("#{'hello'.length()}")

XML配置:

<property name="name" value="#{'hello'.concat('java')}"/>

2 常用語法

SpEL 可以訪問屬性、調用方法、執行算術和邏輯運算、處理集合和數值及使用正則表達式等。

訪問屬性

使用點號(.)來訪問對象的屬性。#{person.name},也可訪問嵌套屬性。#{person.address.city}

訪問數值、列表和集合

使用方括號([])來訪問其元素。#{list[0]}、#{array[0]}、#{map[‘key’]}

調用方法

使用點號(.)或方括號([])來調用方法。#{person.setName(‘hello’)}

運算符

算術運算符、比較運算符、邏輯運算符、三元運算符。

正則表達式

使用關鍵字“matches”。 #{name matches ‘.*word.’}

列表投影和選擇

? 進行列表投影(選擇符合條件的元素);^ 選擇第一個元素,$ 選擇最后一個元素。 #{list.?[#this > 10]}、#{list.^[#this > 10]}

變量引用

可以直接引用bean, 通過@+bean名 來訪問這個bean (解析器需要與容器關聯)。#{@myBean}或者EvaluationContext環境變量。

安全導航操作符

使用? 進行安全導航,避免空指針異常。#{person?.address?.city}、#{person?.name?:‘無名’}

類型運算符

使用T() 告訴表達式將其作為類來處理。#{T(java.lang.String).valueOf(123)}

表 SpEL 的常用語法

public class SpELTest2 {public static void main(String[] args) {Person person = new Person("黃先生", null);SpelExpressionParser parser = new SpelExpressionParser();// 訪問屬性System.out.println(parser.parseExpression("name").getValue(person)); // 黃先生// 訪問數值、列表和集合Map<String,Object> map = new HashMap<>();map.put("username","hmf");List<Map<String,Object>> list = new ArrayList<>();list.add(map);System.out.println(parser.parseExpression("[0]['username']").getValue(list));// hmf// 調用方法parser.parseExpression("showInfo").getValue(person); // Person{name='黃先生', address=null}// 運算符System.out.println(parser.parseExpression("1 + 99 > 43 && '黃先生' == name").getValue(person)); // true// 正則表達式System.out.println(parser.parseExpression("'hello word!' matches '.*hello\\b.*'").getValue()); // true// 列表投影和選擇Integer[] numArray = new Integer[]{12,5,7,66,22,34,1};List<Integer> numList = Arrays.asList(numArray);System.out.println(parser.parseExpression("?[#this > 10]").getValue(numList)); // [12, 66, 22, 34]System.out.println(parser.parseExpression("^[#this > 10]").getValue(numList)); // 12System.out.println(parser.parseExpression("$[#this > 10]").getValue(numList)); // 34// 安全導航操作符System.out.println(parser.parseExpression("address?.city").getValue(person)); // null// 類型運算符System.out.println(parser.parseExpression("T(java.lang.Math).random()").getValue()); // 0.7829801028898056}private static class Person {private String name;private Address address;public Person(String name, Address address) {this.name = name;this.address = address;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}public void showInfo() {System.out.println(this);}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", address=" + address +'}';}}private static class Address {private String province;private String city;public Address(String province, String city) {this.province = province;this.city = city;}public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/711188.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/711188.shtml
英文地址,請注明出處:http://en.pswp.cn/news/711188.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CentOS安裝編譯Python3.11.6

CentOs自帶python2版本太低&#xff0c;項目需要python3&#xff0c;于是自己安裝python 操作指南&#xff1a; 重新下載源代碼&#xff1a; # 刪除舊的 Python 源代碼文件&#xff08;如果有&#xff09; rm -rf Python-3.11.6.tar.xz # 下載 Python 3.11.6 的源代碼文件 wget…

Java泛型簡介

Java泛型簡介 Java泛型是在Java 5中引入的一個特性&#xff0c;它允許程序員在編譯時指定類、接口或方法能夠接受的類型。泛型的主要目的是提供編譯時類型安全檢查&#xff0c;避免在運行時因為類型轉換錯誤而導致的ClassCastException。 在沒有泛型之前&#xff0c;Java中的集…

如何利用動態靜態代理IP實現跨地域網絡營銷與市場研究

動態代理IP和靜態代理IP都可以在跨地域網絡營銷與市場研究中發揮關鍵作用&#xff0c;具體實現方式如下&#xff1a; ### 動態代理IP的應用&#xff1a; 1. 跨地域營銷活動測試&#xff1a; - 在進行網絡營銷時&#xff0c;尤其是要驗證廣告投放、SEO效果或A/B測試不同地區用戶…

Ubuntu系統使用Docker搭建Jupyter Notebook并實現無公網ip遠程連接

文章目錄 1. 選擇與拉取鏡像2. 創建容器3. 訪問Jupyter工作臺4. 遠程訪問Jupyter工作臺4.1 內網穿透工具安裝4.2 創建遠程連接公網地址4.3 使用固定二級子域名地址遠程訪問 本文主要介紹如何在Ubuntu系統中使用Docker本地部署Jupyter Notebook&#xff0c;并結合cpolar內網穿透…

C語言系列(所需基礎:大學C語言及格)-4-轉義字符/注釋/選擇語句

文章目錄 一、轉義字符二、注釋三、選擇語句 一、轉義字符 加上\會講原來的字符改變意思&#xff0c;即進行轉義 例如\t會使t變成\t用于表示轉義字符&#xff0c;使得t轉義成水平制表符 其他轉義字符&#xff1a; 三字母詞&#xff08;展示\&#xff1f;的用處&#xff09;…

C#面:接口是一種引用類型,不可以聲明公有的域或私有的成員變量,但是可以聲明什么呢?

可以聲明&#xff1a;方法&#xff0c;屬性&#xff0c;索引器&#xff0c;事件。 接口的主要作用是定義一套規范&#xff0c;使得不同的類可以按照相同的規范進行交互。通過實現接口&#xff0c;類可以具備多態性&#xff0c;即可以以接口類型來引用對象&#xff0c;并調用接…

k8s-001-Centos7內核升級

1. 查看內核 [rootlocalhost ~]# uname -a 2. 執行的命令(安裝最新版內核): 下載: rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org 安裝: rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm &#xff08; 查看最新版內核&…

杭州默安-安全技術實習生-一面

1.自我介紹 略 2.專業主修的課程 略 3.xss漏洞的類型&#xff0c;原理及防御 原理&#xff0c;服務器對用戶的輸入過濾不嚴格&#xff0c;將用戶的輸入當作Javascript代碼執行并返回給客戶端。 防御&#xff0c;輸入和url參數過濾&#xff0c;HTML實體編碼轉義特殊字符。…

力扣hot100題解(python版33-35題)

33、排序鏈表 給你鏈表的頭結點 head &#xff0c;請將其按 升序 排列并返回 排序后的鏈表 。 示例 1&#xff1a; 輸入&#xff1a;head [4,2,1,3] 輸出&#xff1a;[1,2,3,4]示例 2&#xff1a; 輸入&#xff1a;head [-1,5,3,4,0] 輸出&#xff1a;[-1,0,3,4,5]示例 3&a…

kafka架構詳解

文章目錄 概述kafaka架構Kafka的設計時什么樣的Zookeeper 在 Kafka 中的作用知道 概述 Apache Kafka 是分布式發布 - 訂閱消息系統&#xff0c;在 kafka 官網上對 kafka 的定義&#xff1a;一個分布式發布 - 訂閱消息傳遞系統。 Kafka 最初由 LinkedIn 公司開發&#xff0c;Li…

mysql 中 auto_increment 自增約束的用法和配置

自增約束 int字段 特殊約束條件&#xff0c;用于為表中寫入新的記錄生成唯一的值&#xff0c;一個表中只能有一個自增約束字段 格式 字段 數據類型 auto_increment 創建帶有自增約束的表 create table student_game_auto ( id int unique auto_increment, name char(5),…

螞蟻集團推動編制的全球首個隱私計算一體機國際標準發布

近日&#xff0c;IEEE 標準協會&#xff08;IEEE-SA&#xff09;正式發布并推行了由我國企業主導的全球首個隱私計算一體機國際標準《隱私計算一體機技術要求》&#xff08;IEEE 3156-2023&#xff09;。IEEE-SA是權威國際標準制定機構&#xff0c;該標準的成功發布意味著中國的…

numpy常見操作

返回各維度元組print(img.shape)返回大小img.size返回各維度數據類型print(img.dtype) 數據類型變int8maskmask.astype(np.int8) 注意int32可變float64 但float64變int32會把小數截斷 string_可變float64 NumPy常見操作&#xff1a; import numpy as np 創建一個一維數組 ar…

繼承-學習2

this關鍵字&#xff1a;指向調用該方法的對象&#xff0c;一般我們是在當前類中使用this關鍵字&#xff0c;所以我們常說代表本類對象的引用 super關鍵字&#xff1a;代表父類存儲空間的標識(可看作父類對象的引用) 父類&#xff1a; package ven;public class Fu {//父類成員…

操作系統面經

1. 進程和線程的區別&#xff1f; 調度&#xff1a;進程是資源管理的基本單位&#xff0c;線程是程序執行的基本單位。切換&#xff1a;線程上下文切換比進程上下文切換要快得多。擁有資源&#xff1a; 進程是擁有資源的一個獨立單位&#xff0c;線程不擁有系統資源&#xff0…

unity自定義著色器基礎

這些內置渲染管線的著色器示例演示了編寫自定義著色器的基礎知識&#xff0c;并涵蓋了常見的用例。 有關編寫著色器的信息&#xff0c;請參閱編寫著色器。 設置場景 第一步是創建一些用于測試著色器的對象。在主菜單中選擇 Game Object > 3D Object > Capsule。然后&a…

高光譜遙感學習入門丨高光譜數據處理基礎、Python和Matlab高光譜遙感數據處理

目錄 ①Python高光譜遙感數據處理與高光譜遙感機器學習方法深度應用 ②Matlab高光譜遙感、數據處理與混合像元分解實踐技術應用 ③高光譜遙感數值建模技術及在植被、水體、土壤信息提取領域應用 更多應用 高光譜遙感信息對于我們認識世界具有重要意義。盡管大部分物質在人眼…

記錄 | docker權限原因導致service ssh start失敗

【報錯】 容器內啟 ssh server 報錯 有兩個錯&#xff1a; &#xff08;1&#xff09;/etc/ssh/sshd_host_rsa_key 權限太高&#xff1b; &#xff08;2&#xff09;/run/sshd用戶組不為 root 解決方法&#xff1a; 方法一&#xff1a; 各自容器內對/etc/ssh/sshd_host_r…

【前端素材】推薦優質后臺管理系統 Adminity平臺模板(附源碼)

一、需求分析 1、系統定義 后臺管理系統是一種用于管理網站、應用程序或系統的管理界面&#xff0c;通常由管理員和工作人員使用。它提供了訪問和控制網站或應用程序后臺功能的工具和界面&#xff0c;使其能夠管理用戶、內容、數據和其他各種功能。 2、功能需求 后臺管理系…

2024年四川媒體新聞發布渠道,媒體邀約資源表

傳媒如春雨&#xff0c;潤物細無聲&#xff0c;大家好&#xff0c;我是51媒體網胡老師。 四川有哪些媒體新聞發布渠道&#xff0c;媒體邀約資源表&#xff1f; 2024年四川媒體新聞發布渠道&#xff0c;媒體邀約資源表 四川本地媒體&#xff1a;如四川日報、華西都市報、成都商…