基于springEL表達(dá)式詳解及應(yīng)用
基于springEL表達(dá)式詳解及應(yīng)用
什么是SpringEL?
Spring3中引入了Spring表達(dá)式語言—SpringEL,SpEL是一種強(qiáng)大,簡潔的裝配Bean的方式,他可以通過運(yùn)行期間執(zhí)行的表達(dá)式將值裝配到我們的屬性或構(gòu)造函數(shù)當(dāng)中,更可以調(diào)用JDK中提供的靜態(tài)常量,獲取外部Properties文件中的的配置
為什么要使用SpringEL?
我們平常通過配置文件或Annotaton注入的Bean,其實(shí)都可以稱為靜態(tài)性注入,試想一下,若然我Bean A中有變量A,它的值需要根據(jù)Bean B的B變量為參考,在這場景下靜態(tài)注入就對這樣的處理顯得非常無力,而Spring3增加的SpringEL就可以完全滿足這種需求,而且還可以對不同Bean的字段進(jìn)行計(jì)算再進(jìn)行賦值,功能非常強(qiáng)大
如何使用SpringEL?
SpringEL從名字來看就能看出,和EL是有點(diǎn)關(guān)系的,SpringEL的使用和EL表達(dá)式的使用非常相似,EL表達(dá)式在JSP頁面更方便的獲取后臺中的值,而SpringEL就是為了更方便獲取Spring容器中的Bean的值,EL使用${},而SpringEL使用#{}進(jìn)行表達(dá)式的聲明。
使用SpringEL注入簡單值
public class TestSpringEL {
/*
* @Value注解等同于XML配置中的<property/>標(biāo)簽,
* SpringEL同樣支持在XML<property/>中編寫
*/
// 注入簡單值,輸出num為5
@Value("#{5}")
private Integer num;
// 注入ID為testConstant的Bean
@Value("#{testConstant}")
private TestConstant Constant;
// 注入ID為testConstant Bean中的STR常量/變量
@Value("#{testConstant.STR}")
private String str;
}
使用SpringEL調(diào)用方法
public class TestSpringEL {
/*
* TestConstant類中有兩個(gè)方法重載,
* 返回值為String類型
*/
// 調(diào)用無參方法
@Value("#{testConstant.showProperty}")
private String method1;
// 有參接收字符串的方法
@Value("#{testConstant.showProperty('Hello')}")
private String method2;
/*
* 若然希望方法返回的String為大寫
*/
@Value("#{testConstant.showProperty().toUpperCase()}")
private String method3;
/*
* 若使用method3這種方式,若然showProperty返回為null,
* 將會(huì)拋出NullPointerException,可以使用以下方式避免
*/
@Value("#{testConstant.showProperty()?.toUpperCase}")
private String method4;
/*
* 使用?.符號代表若然左邊的值為null,將不執(zhí)行右邊方法,
* 讀者可以靈活運(yùn)用在其他場景,只要左邊可能返回null,
* 即可使用上面示例中的?.
*/
}
SpringEL調(diào)用靜態(tài)類或常量
public class TestSpringEL {
/*
* 注入JDK中的工具類常量或調(diào)用工具類的方法
*/
// 獲取Math的PI常量
@Value("#{T(java.lang.Math).PI")
private double pi;
// 調(diào)用random方法獲取返回值
@Value("#{T(java.lang.Math).random()}")
private double ramdom;
// 獲取文件路徑符號
@Value("#{T(java.io.File).separator}")
private String separator;
}
SpringEL運(yùn)算
public class TestSpringEL {
/*
* 使用SpringEL進(jìn)行運(yùn)算及邏輯操作
*/
// 拼接字符串
@Value("#{testConstant.nickname + ' ' + testConstant.name}")
private String concatString;
// 對數(shù)字類型進(jìn)行運(yùn)算,testConstant擁有num屬性
@Value("#{ 3 * T(java.lang.Math).PI + testConstant.num}")
private double operation;
// 進(jìn)行邏輯運(yùn)算
@Value("#{testConstant.num > 100 and testConstant.num <= 200}")
private boolean logicOperation;
// 進(jìn)行或非邏輯操作
@Value("#{ not testConstant.num == 100 or testConstant.num <= 200}")
private boolean logicOperation2;
// 使用三元運(yùn)算符
@Value("#{testConstant.num > 100 ? testConstant.num : testConstant.num + 100}")
private Integer logicOperation3;
}
SpringEL使用正則表達(dá)式
public class TestSpringEL {
// 驗(yàn)證是否郵箱地址正則表達(dá)式
@Value("#{testConstant.STR match '\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+'}")
private boolean regularExpression;
}
SpringEL操作集合
public class TestSpringEL {
/*
* TestConstant類中擁有名為testList的List變量, 和名為testMap的Map
*/
// 獲取下標(biāo)為0的元素
@Value("#{testConstant.testList[0]}")
private String str;
// 獲取下標(biāo)為0元素的大寫形式
@Value("#{testConstant.testList[0]?.toUpperCase()}")
private String upperStr;
// 獲取map中key為hello的value
@Value("#{testConstant.testMap['hello']}")
private String mapValue;
// 根據(jù)testList下標(biāo)為0元素作為key獲取testMap的value
@Value("#{testConstant.testMap[testConstant.testList[0]]}")
private String mapStrByTestList;
}
Spring操作外部Properties文件
<!-- 首先通過applicaContext.xml中<util:properties>增加properties文件 --> <!-- 注意需要引入Spring的util schemea命名空間和注意id屬性,id屬性將在SpringEL中使用 --> <util:properties id="test" location="classpath:application.properties"/>
public class TestSpringEL {
// 注意test為xml文件中聲明的id
@Value("#{test['jdbc.url']}")
private String propertiesValue;
}
SpringEL查詢篩選集合和投影
public class TestSpringEL {
/*
* 聲明City類,有population屬性 testContants擁有名叫cityList的City類List集合
*/
// 過濾testConstant中cityList集合population屬性大于1000的全部數(shù)據(jù)注入到本屬性
@Value("#{testConstant.cityList.?[population > 1000]}")
private List<City> cityList;
// 過濾testConstant中cityList集合population屬性等于1000的第一條數(shù)據(jù)注入到本屬性
@Value("#{testConstant.cityList.^[population == 1000]}")
private City city;
// 過濾testConstant中cityList集合population屬性小于1000的最后一條數(shù)據(jù)注入到本屬性
@Value("#{testConstant.cityList.$[population < 1000]}")
private City city2;
/*
* 首先為city增加name屬性,代表城市的名稱
*/
/*
* 假如我們在過濾城市集合后只想保留城市的名稱,
* 可以使用如下方式進(jìn)行投影
*/
@Value("#{testConstant.cityList.?[population > 1000].![name]}")
private List<String> cityName;
}
優(yōu)點(diǎn):
SpringEL功能非常強(qiáng)大,在Annotation的方式開發(fā)時(shí)可能感覺并不強(qiáng)烈,因?yàn)榭梢灾苯泳帉懙皆创a來實(shí)現(xiàn)SpringEL的功能,但若然是在XML文件中進(jìn)行配置,SpringEL可以彌補(bǔ)XML靜態(tài)注入的不足,從而實(shí)現(xiàn)更強(qiáng)大的注入
缺點(diǎn):
SpringEL在使用時(shí)僅僅是一個(gè)字符串,不易于排錯(cuò)與測試,也沒有IDE檢查我們的語法,當(dāng)出現(xiàn)錯(cuò)誤時(shí)較難檢測
筆者實(shí)際應(yīng)用:
筆者開發(fā)的項(xiàng)目當(dāng)中比較頻繁的使用SpringEL,例如通過SpringEL獲取外部properties中的值,又或者項(xiàng)目當(dāng)中的數(shù)據(jù)字典亦是使用SpringEL的一個(gè)場景,我們抽象出一個(gè)Param類的集合,通過SpringEL集合篩選和投影獲取我們想要的字段參數(shù)添加到我們的程序邏輯當(dāng)中(筆者項(xiàng)目中的Spring Security亦使用SpringEL,但本文章不加以敘述)
總結(jié):
Spring3.0讓人為之驚艷的非SpringEL莫屬,為我們的注入提供了另一種強(qiáng)大的形式,傳統(tǒng)注入能做到的事情,和做不到的事情,SpringEL一概能完成,但在項(xiàng)目當(dāng)中并不適宜大量使用SpringEL,適當(dāng)?shù)募夹g(shù)方在適當(dāng)?shù)奈恢?,才能更好的完成事情?/p>
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java讀寫excel文件實(shí)現(xiàn)POI解析Excel的方法
在日常工作中,我們常常會(huì)進(jìn)行Excel文件讀寫操作,這篇文章主要介紹了java讀寫excel文件實(shí)現(xiàn)POI解析Excel的方法,實(shí)例分析了java讀寫excel的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-10-10
Java實(shí)現(xiàn)CSV格式轉(zhuǎn)對象
csv全稱“Comma-Separated Values”,是一種逗號分隔值格式的文件,常用來存儲數(shù)據(jù)的純文本格式文件。本文將用Java語言實(shí)現(xiàn)CSV轉(zhuǎn)對象,需要的可以參考一下2022-06-06
詳解spring cloud config實(shí)現(xiàn)datasource的熱部署
這篇文章主要介紹了詳解spring cloud config實(shí)現(xiàn)datasource的熱部署,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-01-01
源碼分析Spring?中?@Qualifier?注解基本用法
這篇文章主要介紹了源碼分析Spring?中?@Qualifier?注解基本用法,在源碼分析的過程中,也?GET?到?Spring?許多新的玩法,感興趣的小伙伴趕緊去試試吧2023-08-08
java實(shí)現(xiàn)潛艇大戰(zhàn)游戲源碼
潛艇大戰(zhàn)游戲相信大家都玩過,是一款非常有趣的小游戲,那么基于代碼是如何實(shí)現(xiàn)的呢?今天小編給大家?guī)硪黄坛處椭蠹覍W(xué)習(xí)java實(shí)現(xiàn)潛艇大戰(zhàn)游戲,感謝的朋友一起看看吧2021-06-06
Intellij IDEA實(shí)現(xiàn)SpringBoot項(xiàng)目多端口啟動(dòng)的兩種方法
有時(shí)候使用springboot項(xiàng)目時(shí)遇到這樣一種情況,用一個(gè)項(xiàng)目需要復(fù)制很多遍進(jìn)行測試,除了端口號不同以外,沒有任何不同。遇到這種情況怎么辦呢?這時(shí)候可以使用Intellij IDEA解決2018-06-06
Mybatis Plus 實(shí)現(xiàn)批量插入的示例代碼
本文主要介紹了Mybatis Plus 實(shí)現(xiàn)批量插入的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
Java算法之BFS,DFS,動(dòng)態(tài)規(guī)劃和貪心算法的實(shí)現(xiàn)
廣度優(yōu)先搜索(BFS)和深度優(yōu)先搜索(DFS)是圖遍歷算法中最常見的兩種算法,主要用于解決搜索和遍歷問題。動(dòng)態(tài)規(guī)劃和貪心算法則用來解決優(yōu)化問題。本文就來看看這些算法的具體實(shí)現(xiàn)吧2023-04-04

