初次遇見@Value注解的時候,總以為它的功能非常生硬,只能注入硬編碼的字面量值,后來隨著學習的深入,漸漸發現@Value注解也能注入屬性檔案的值,非常好用,讓人格外驚喜的是,@Value注解并未止步于此,還提供了通過Spring運算式語言(Spring Expression Language, SpEL)注入更加豐富的值的支持,比如,com.dream包定義了這樣的類:
1 public class MusicWorld { 2 public static final String DREAM = "Dream"; 3 }
則可這樣把SpEL運算式的運算結果注入Bean中:
1 @Component 2 public class Music { 3 private String musicName = null; 4 5 @Value("#{T(com.dream.MusicWorld).DREAM + ' work'}") 6 public void setMusicName(String musicName) { 7 this.musicName = musicName; 8 } 9 10 // 省略getter方法 11 }
可以看到musicName屬性帶有@Value注解,其值是括在 #{} 里的SpEL運算式 T(com.dream.MusicWorld).DREAM + ' work' ,這樣,Spring容器瞧見@Value注解之后就能決議SpEL運算式,把靜態常量MusicWord.DREAM_MUSIC與字串 work 連接之后得到字串 Dream work 注入musicName屬性里了,
非常明顯,Spring運算式語言能夠使用運算式描述值的注入,告訴Spring容器在運行時決議運算式之后把決議出來的結果注入Bean中,SpEL運算式必須括在 #{} 里,既可呼叫類的靜態成員,Bean的實體成員;也可使用各種運算子進行值的運算,功能非常強大,語法非常簡潔,用法非常方便,大大豐富了值的注入,現在,讓我們一起瞧瞧SpEL運算式支持的功能,
SpEL運算式與字面量值
這是最簡單的一種SpEL運算式,只要把硬編碼的數字,布林值,字串等字面量值括在 #{} 里,就能通過SpEL運算式注入字面量值了,其中,字串需要括在兩個單引號 ' 里,如果需要注入的字串本身就有單引號,可用兩個單引號 '' 表示,以下示例就注入了字串 One's dream :
1 @Component 2 public class Music { 3 private String musicName = null; 4 5 @Value("#{'One''s dream'}") 6 public void setMusicName(String musicName) { 7 this.musicName = musicName; 8 } 9 10 // 省略getter方法 11 }
SpEL運算式與集合
SpEL運算式支持集合的注入,如果集合的型別是Array,List或Set,可把集合的值使用逗號隔開之后括在 {} 里,如下所示:
1 @Component 2 public class Music { 3 private String[] musicNameArray = null; 4 private List<String> musicNameList = null; 5 private Set<String> musicNameSet = null; 6 7 @Value("#{{'One', 'Two', 'Three'}}") 8 public void setMusicNameArray(String[] musicNameArray) { 9 this.musicNameArray = musicNameArray; 10 } 11 12 @Value("#{{'One', 'Two', 'Three'}}") 13 public void setMusicNameList(List<String> musicNameList) { 14 this.musicNameList = musicNameList; 15 } 16 17 @Value("#{{'One', 'Two', 'Three'}}") 18 public void setMusicNameSet(Set<String> musicNameSet) { 19 this.musicNameSet = musicNameSet; 20 } 21 22 // 省略getter方法 23 }
如果集合的型別是Map,能以 鍵: 值 表示一對鍵值,而后把多對鍵值使用逗號隔開之后括在 {} 里,如下所示:
1 @Component 2 public class Music { 3 private Map<String, String> musicNameMap = null; 4 5 @Value("#{{OneKey: 'One', TwoKey: 'Two', ThreeKey: 'Three'}}") 6 public void setMusicNameMap(Map<String, String> musicNameMap) { 7 this.musicNameMap = musicNameMap; 8 } 9 10 // 省略getter方法 11 }
訪問Bean的屬性
SpEL運算式支持以 Bean的ID.Bean的屬性名 這樣的方式訪問Spring容器里的Bean的屬性,假如com.dream包定義了這樣的組件:
1 @Component("music") 2 public class Music { 3 private String musicName = null; 4 5 @Value("Dream") 6 public void setMusicName(String musicName) { 7 this.musicName = musicName; 8 } 9 10 // 省略getter方法 11 }
則可這樣訪問ID為music的Bean的musicName屬性,把它的值注入player中:
1 @Component("player") 2 public class Player { 3 private String playingMusicName = null; 4 5 @Value("#{music.musicName}") 6 public void setPlayingMusicName(String playingMusicName) { 7 this.playingMusicName = playingMusicName; 8 } 9 10 // 省略getter方法 11 }
訪問Array,List,Set的值
SpEL運算式支持通過中括號 [] 括起索引訪問Array,List,Set的值,假如com.dream包定義了這樣的組件:
1 @Component("music") 2 public class Music { 3 private String[] musicNameArray = null; 4 private List<String> musicNameList = null; 5 private Set<String> musicNameSet = null; 6 7 @Value("#{{'One', 'Two', 'Three'}}") 8 public void setMusicNameArray(String[] musicNameArray) { 9 this.musicNameArray = musicNameArray; 10 } 11 12 @Value("#{{'One', 'Two', 'Three'}}") 13 public void setMusicNameList(List<String> musicNameList) { 14 this.musicNameList = musicNameList; 15 } 16 17 @Value("#{{'One', 'Two', 'Three'}}") 18 public void setMusicNameSet(Set<String> musicNameSet) { 19 this.musicNameSet = musicNameSet; 20 } 21 22 // 省略getter方法 23 }
則可這樣指定索引取出Array,List,Set的值,把它們注入player中:
1 @Component("player") 2 public class Player { 3 private String playingMusicName_1 = null; 4 private String playingMusicName_2 = null; 5 private String playingMusicName_3 = null; 6 7 @Value("#{music.musicNameArray[0]}") 8 public void setPlayingMusicName_1(String musicName) { 9 this.playingMusicName_1 = musicName; 10 } 11 12 @Value("#{music.musicNameList[0]}") 13 public void setPlayingMusicName_2(String musicName) { 14 this.playingMusicName_2 = musicName; 15 } 16 17 @Value("#{music.musicNameSet[0]}") 18 public void setPlayingMusicName_3(String musicName) { 19 this.playingMusicName_3 = musicName; 20 } 21 22 // 省略getter方法 23 }
訪問Map的值
SpEL運算式支持通過中刮號 [] 括起Map的鍵訪問Map的值,假如com.dream包定義了這樣的組件:
1 @Component("music") 2 public class Music { 3 private Map<String, String> musicNameMap = null; 4 5 @Value("#{{OneKey: 'One', TwoKey: 'Two', ThreeKey: 'Three'}}") 6 public void setMusicNameMap(Map<String, String> musicNameMap) { 7 this.musicNameMap = musicNameMap; 8 } 9 10 // 省略getter方法 11 }
則可這樣指定Map的鍵取出Map的值,把它注入player中:
1 @Component("player") 2 public class Player { 3 private String playingMusicName = null; 4 5 @Value("#{music.musicNameMap['OneKey']}") 6 public void setPlayingMusicName(String playingMusicName) { 7 this.playingMusicName = playingMusicName; 8 } 9 10 // 省略getter方法 11 }
呼叫Bean的方法
SpEL運算式支持通過 Bean的ID.Bean的方法 這樣的方式呼叫Spring容器里的Bean的方法,假如com.dream包定義了這樣的組件:
1 @Component("music") 2 public class Music { 3 private String musicName = null; 4 5 @Value("Dream") 6 public void setMusicName(String musicName) { 7 this.musicName = musicName; 8 } 9 10 public String appendMusicName(String appendValue) { 11 return this.musicName + appendValue; 12 } 13 14 // 省略getter方法 15 }
則可這樣呼叫ID為music的Bean的appendMusicName方法,把它的回傳值注入player中:
1 @Component("player") 2 public class Player { 3 private String playingMusicName = null; 4 5 @Value("#{music.appendMusicName(' work')}") 6 public void setPlayingMusicName(String playingMusicName) { 7 this.playingMusicName = playingMusicName; 8 } 9 10 // 省略getter方法 11 }
T()運算子
SpEL運算式提供了T()運算子用于獲取類的Class物件,只要把全限定類名指給T()運算子,T()運算子即能獲取指定類的Class物件,因此,假如com.dream包定義了這樣的類:
1 public class MusicWorld { 2 public static final String DREAM = "Dream"; 3 }
則可這樣通過SpEL運算式獲取MusicWorld的Class物件,把它注入music中:
1 @Component("music") 2 public class Music { 3 private Class musicWorldClass = null; 4 5 @Value("#{T(com.dream.MusicWorld)}") 6 public void setMusicWorldClass(Class musicWorldClass) { 7 this.musicWorldClass = musicWorldClass; 8 } 9 10 // 省略getter方法 11 }
一種常用的用法是使用T()運算子獲取類的Class物件之后訪問類的靜態成員,如下所示:
1 @Component("music") 2 public class Music { 3 private String musicName = null; 4 5 @Value("#{T(com.dream.MusicWorld).DREAM}") 6 public void setMusicName(String musicName) { 7 this.musicName = musicName; 8 } 9 10 // 省略getter方法 11 }
matches運算子
SpEL運算式支持通過matches運算子,以 字串 matches 正則運算式 這樣的方式判斷某個字串是否匹配某個正則運算式:如果匹配,則回傳TRUE;否則回傳FALSE,因此,假如com.dream包定義了這樣的組件:
1 @Component("music") 2 public class Music { 3 private String musicName = null; 4 5 @Value("Dream") 6 public void setMusicName(String musicName) { 7 this.musicName = musicName; 8 } 9 10 // 省略getter方法 11 }
則可這樣在SpEL運算式里使用matches運算子,看看music的musicName屬性的值是不是只有字母,并把運算結果注入player中:
1 @Component("player") 2 public class Player { 3 private boolean isMusicValid = false; 4 5 @Value("#{music.musicName matches '^[a-zA-Z]+$'}") 6 public void setIsMusicValid(boolean isMusicValid) { 7 this.isMusicValid = isMusicValid; 8 } 9 10 // 省略getter方法 11 }
new運算子
SpEL運算式支持通過new運算子,以 new 帶有全限定類名的建構式 這樣的方式創建類的實體,假如com.dream包定義了這樣的類:
1 public class Music { 2 private String musicName = null; 3 4 public Music(String musicName) { 5 this.musicName = musicName; 6 } 7 }
則可這樣在SpEL運算式里使用new運算子創建Music類的實體,把實體注入player中:
1 @Component("player") 2 public class Player { 3 private Music playingMusic = null; 4 5 @Value("#{new com.dream.Music('Dream')}") 6 public void setMusic(Music playingMusic) { 7 this.playingMusic = playingMusic; 8 } 9 10 // 省略getter方法 11 }
關系運行符
SpEL運算式提供了這些用于進行關系運算的關系運算子:
1.小于:< (也可使用文本lt)
2.大于:> (也可使用文本gt)
3.小于等于:<= (也可使用文本le)
4.大于等于:>= (也可使用文本ge)
5.等于:== (也可使用文本eq)
6.不等于:!= (也可使用文本ne)
這些關系運算子的用法與Java的關系運算子是一樣,大家一瞧便知,不再詳敘,
邏輯運算子
SpEL運算式提供了這些用于進行邏輯運算的邏輯運算子:
1.與:and
2.或:or
3.非:not
這些邏輯運算子的用法與Java的邏輯運算子是一樣,大家一瞧便知,不再詳敘,
算數運算子
SpEL運算式提供了這些用于進行算數運算的算數運算子:
1.數字的相加或字串的相連:+
2.減:-
3.乘:*
4.除:/
5.取模:%
6.乘方:^
這些算術運算子的用法與Java的算術運算子是一樣,大家一瞧便知,不再詳敘,
?:運算子
SpEL運算式提供的?:運算子具有兩種用法:一種是作為三元運算子(Ternary Operator)用于If-Then-Else的條件運算;一種是作為Elvis運算子用于簡化三元運算子關于null值的用法,
?:運算子用作三元運算子時,它的用法和Java的?:運算子是一樣的,如下所示:
1 #{music.musicName != null ? music.musicName: 'There is not any music.'}
這條SpEL運算式會先檢查 music.musicName 的值是否不等于null:如果不等于null,則回傳 music.musicName 的值;否則回傳字串 There is not any music.
另外,這條SpEL運算式還能使用Elvis運算子這樣簡化:
1 #{music.musicName ?: 'There is not any music.'}
Elvis運算子會先檢查 music.musicName 的值是否不等于null:如果不等于null,則直接回傳自己,也就是回傳
music.musicName 的值;否則回傳 ?: 后面的值,也就是回傳字串 There is not any music.
?.運算子
SpEL運算式提供了?.運算子用于安全地訪問Bean的屬性,呼叫Bean的方法,按照以往的寫法,我們總是這樣訪問Bean的屬性,呼叫Bean的方法:
1 #{music.musicName} 2 #{music.appendMusicName(' work')}
毫無疑問,如果music等于null,程式定會拋出例外,為了避免這樣的錯誤,我們可用?.運算子修改如下:
1 #{music?.musicName} 2 #{music?.appendMusicName(' work')}
我們把 . 換成了?.運算子,這樣,當music等于null時,這條SpEL運算式只會回傳null,不會拋出例外;當music不等于null時,這條SpEL運算式才會訪問Bean的屬性,呼叫Bean的方法,
至此,關于SpEL運算式的介紹該告一段落了,當然,XML組態檔也是支持SpEL運算式的,而且用法與@Value注解一模一樣,大家一看下面的示例就知道了:
1 <bean id="music_1" class="com.dream.Music"> 2 <property name="musicName" 3 value="#{T(com.dream.MusicWorld).DREAM + ' work'}" /> 4 </bean> 5 <bean id="music_2" class="com.dream.Music"> 6 <constructor-arg type="java.lang.String" 7 value="#{T(com.dream.MusicWorld).DREAM + ' work'}" /> 8 </bean>
下章,我們將會開始介紹Profile,歡迎大家繼續閱讀,謝謝大家!
回傳目錄 下載代碼
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/424920.html
標籤:其他
上一篇:哈撒給,英雄聯盟全皮膚下載器來了
下一篇:JVM的垃圾回識訓制
