Spring 3.0參考手冊之SpEL

Spring 3.0 RC1發佈,一些新特性很吸引人,看了一下Reference,順便翻譯了SpEL這節,水平有限,還望指教。

Spring 3.0 Reference:http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/index.html

 

Part III 核心技術

6.Spring 表達式語言(SpEL)

 

  • 6.1 簡介
  • 6.2 特性概覽
  • 6.3 使用Spring Expression接口進行表達式求值
  • 6.4 bean定義的表達式支持
  • 6.5 語言參考
  • 6.6 示例類

 6.1 簡介

    Spring表達式語言(簡稱SpEL)是一個支持運行時查詢和操作對象圖的強大的表達式語言。其語法類似於統一EL,但提供了額外特性,顯式方法調用和基本字符串模板函數。

    同很多可用的Java 表達式語言相比,例如OGNLMVELJBoss ELSpEL的誕生是爲了給Spring社區提供一個可以給Spring目錄中所有產品提供單一良好支持的表達式語言。其語言特性由Spring目錄中的項目需求驅動,包括基於eclipseSpringSource套件中的代碼補全工具需求。那就是說,SpEL是一個基於技術中立的API允許需要時與其他表達式語言集成。

    SpEL作爲Spring目錄中表達式求值的基礎,它並不是直接依賴於Spring而是可以被獨立使用。爲了能夠自包含,本章中的許多示例把SpEL作爲一個獨立的表達式語言來使用。這就需要創建一些如解析器的引導基礎組件類。大多數Spring用戶只需要爲求值編寫表達式字符串而不需要關心這些基礎組件。一個典型的使用例子是集成SpEL和創建基於XML或註解的bean定義,見6.4 bean定義的表達式支持一節。

    本章涵蓋了表達式語言的特性,API和語法。在很多地方,一個Inventor類和InvertorSociety類作爲表達式求值的目標對象。這些類聲明和操作它們使用的數據列在本章的末尾。

6.2 特性概覽

    表達式語言支持下列功能:

   字符表達式

   布爾和關係操作符

   正則表達式

   類表達式

   訪問propertiesarrayslistsmaps

   方法調用

   關係操作符

   賦值

   調用構造器

   三元操作符

   變量

   用戶自定義函數

   集合投影

   集合選擇

   模板表達式

6.3 使用Spring Expression接口進行表達式求值

    這一節介紹SpEL接口和其表達式語言的簡單實用。完整的語言參考參見語言參考一節。

    下面的代碼使用SpEL API求字符表達式‘Hello World’的值。

    

    message變量的值是最簡單的‘Hello World’。

    最常使用的SpEL類和接口在包org.springframework.expression和其子包以及spel.support中。

    ExpressionParser接口用來解析一個表達式字符串。在這個例子中,表達式串是一個被單引號包括標註的字符串。Expression接口用來求前面定義的表達式串的值。當調用parser.parseExpressionexp.getValue時分別可能拋出ParseExceptionEvaluationException異常。

    SpEL支持一系列特性,例如方法調用,訪問屬性和調用構造器。

    下面調用字符串文字的concat方法作爲方法調用的一個例子。

     

message的值爲‘Hello World!’。

下面的String屬性Bytes可以被調用作爲調用JavaBean屬性的一個例子。

 

SpEL使用標準的‘.’符號支持屬性嵌套和屬性設值,例如:prop1.prop2.prop3.

公共屬性也可以被訪問。

 

使用字符串構造器而不是字符串文字。

 

記住使用泛型方法public < T> T getValue(Class<T> desiredResultType)。使用這個方法省去了需要時對表達式的值顯式類型轉換。如果該值不能被轉換爲T或者使用已註冊的類型轉換器轉換則會拋出EvaluationException.

SpEL中更常見的用途是提供一個針對特定對象實例求值的表達式字符串。在下面的例子中,我們檢索一個Inventor類的實例的name屬性。

 

在最後一行,該字符串變量'name'將被設置爲“Nikola Tesla”。類StandardEvaluationContext是您可以指定對象的將被求值的“name”屬性。你可以重複使用相同的表達式,在求值上下文內設定一個新的根對象。表達式是使用反射求值。

Note在單獨使用SpEL時,你需要創建一個解析器並提供一個求值上下文。但是更爲廣泛的應用僅僅提供一個SpEL表達式字符串作爲配置文件的一部分。例如爲Spring beanSpring Web Flow定義。這種情況下,解析器,求值上下文,根對象和其他預定義變量都會被隱含創建。

作爲最後一個例子,使用前面例子中的Inventor對象中使用布爾操作符。

 

EvaluationContext接口

    EvaluationContext接口用來求一個解析屬性,方法,域的表達式值以及幫助類型轉換。其即插即用實現StandardEvaluationContext使用反射機制來操作對象。爲獲得好的性能緩存java.lang.reflectMethod,Field,Constructor實例。

    StandardEvaluationContext是你用來通過方法setRootObject指定求值根對象或傳遞根對象到構造器的接口。你還可以指定將在表達式中使用的方法setVariableregisterFunction的變量和函數。變量和函數使用的描述見語言參考部分的變量函數StandardEvaluationContext還是你可以註冊自定義ConstructorResolversMethodResolvers,和PropertyAccessors來擴展SpEL如何計算表達式。請參閱這些類的JavaDoc瞭解詳情

類型轉換

    默認情況下,SpEL使用的轉換服務可在Spring的核心(org.springframework.core.convert.ConversionService)找到。這種轉換的服務由很多內建的爲通常轉換的轉換器構成,但也是可擴展的,這樣可以添加自定義類型之間的轉換。此外它的主要支持是它是泛型敏感的。這意味着,當處理表達式中的泛型時,SpEL將嘗試轉換來維持對所遇到的任何對象類型的正確性。 

這是什麼在實踐中意味着什麼呢?比如賦值,用setValue()來設置List類型,實際是List<Boolean>SpEL將會認識到,在List的元素需要在使用之前轉換爲布爾類型。一個簡單的例子:

 

6.4 bean定義的表達式支持

    SpEL可以和Bean定義中基於XML或註解的元數據配置一起使用。兩種情況下的語法都是如#{ <expression string> }的形式。

基於XML的配置

    下面一個屬性或者構造參數值可以使用表達式設值。

     

    變量‘systemProperties’是預先定義的,所以你可以在表達式中如下使用,記住在這個上下文中你不必在預定義的變量前加#號。

    

你可以通過名字引用其他bean的屬性,如下:

 

基於註解的配置

    @Value註解可以在域,方法和方法/構造器參數中使用來指定一個默認值。

    這是一個設置域變量默認值的例子。

 

和下面在屬性的setter方法中使用等價。

 

    自動裝配的方法和構造器同樣可以使用@Value註解。

 

6.5 語言參考

文字表達式

    支持的文字表達的類型是字符串,日期,數值(整型,實型,和十六進制),布爾和空。字符串是由單引號分隔。使用反斜槓字符轉移把一個單引號字符本身放在字符串中。以下清單顯示文字的簡單用法。通常它們不會使用這樣單獨使用,而是作爲一個更復雜的表達式的一部分,例如,使用一個文字表達式作爲邏輯比較運算符的一邊。

 

    數字支持負號,指數符號的使用和小數點。默認情況下實數解析使用Double.parseDouble()。

PropertiesArraysListsMapsIndexers

    用屬性引用導航很簡單,只需使用一個句點來表示一個嵌套的屬性值。Inventor類實例,pupintesla,使用示例中使用的類一節中列出的數據填充。要向下導航並獲得tesla的出生年份和pupin的出生的城市則使用下列表達式。

 

    屬性名的首字母區分大小寫,數組和列表的內容使用方括號符號得到。

 

Map的內容通過指定括號內的文字鍵值得到。在這種情況下,因爲Officers Map的鍵是字符串,我們可以指定字符串。

 

方法

方法調用採用典型的Java編程語法。您還可以調用文字的方法。可變參數也支持。

 

操作符

    關係操作符

    使用標準的操作符號支持關係操作符:等於,不等於,小於,小於等於,大於,大於等於。

 

    除此之外,SpEL支持‘instanceof’和基於正則表達式的‘match’操作。

//evaluatestofalse

boolean falseValue=parser.parseExpression("'xyz'instanceofT(int)").getValue(Boolean.class);

//evaluatestotrue

boolean trueValue=

parser.parseExpression("'5.00'matches'^-?//d+(//.//d{2})?$'").getValue(Boolean.class);

//evaluatestofalse

boolean falseValue=

parser.parseExpression("'5.0067'matches'^-?//d+(//.//d{2})?$'").getValue(Boolean.class);

    邏輯操作符

    支持的邏輯操作符包括andornot,使用方法如下。

 

算術操作符

加法運算符可以用於數字,字符串和日期。減法可用於數字和日期。乘法和除法僅可以用於。其他支持的數學運算包括取模(%)和指數冪(^)。使用標準的運算符優先級。這些運算符示例如下。

 

賦值

    屬性設置是通過使用賦值運算符。這通常是在調用setValue中執行但也可以在調用getValue內。

 

類型

特殊的‘T'操作符可以用來指定一個java.lang.Class的實例('類型')。靜態方法調用也使用此操作符。該StandardEvaluationContext使用TypeLocator尋找類型,StandardTypeLocator(可更換)建立在java.lang包的基礎上。這意味着T()引用在java.lang中的類型不須被完全限定,但所有其他類型的引用必須。

 

構造器

可以使用new運算符調用構造器。完全限定類名應被用於所有類型除了原始類型和字符串(如整型,浮點,等等,可以使用)。

 

變量

變量可以在表達式中使用語法#’變量名引用。變量設置使用StandardEvaluationContext的方法setVariable

 

    #this變量

    #this變量通常被定義和引用當前求值對象(該對象的不合格引用將解決)。

 

函數

    你可以通過註冊可在表達式字符串內調用的用戶自定義函數來擴展SpEL。使用StandardEvaluationContext中的下列方法註冊函數。

 

    所引用的Java方法實現該函數,例如如下這個有用的反轉字符串方法。

 

    隨後這個方法就可以在求值上下文註冊並在表達式字符串中使用了。

 

三元操作符(If-Then-Else

    可以在表達式內使用if-then-else條件邏輯三元操作符。下面是個小例子:

 

    這個情況下,布爾false結果返回‘falseExp‘字符串,一個真實的例子如下:

 

    下一節將看到三元操作符更短的語法Elvis操作符。

Elvis操作符

    ElvIs操作符是Groovy語言中使用的三元操作符的縮短。在三元運算符中通常要重複變量兩次,例如:

 

可以使用Elvis操作符替代,命名爲和Elvis相似的風格。

 

這裏是一個複雜的例子。

 

安全導航操作符

    安全導航操作符來源於Groovy語言,它避免了空指針異常。通常當你有一個對象的引用,在訪問其方法或屬性時你需要驗證該引用是否爲空。爲了避免這種情況,安全導航操作符,只會返回null而不是拋出異常。

 

集合選擇

    選擇是一個強大的表達式語言特性,它允許你通過從入口選擇將原集合轉換爲其他集合。

選擇使用語法?[selectExpression]。這將過濾原集合並返回包含原集合子集的新的集合。例如,選擇將允許我們很容易得到Serbian 發明者列表。

 

    通常是對ListMap的選擇。在前一種情況下的選擇標準是針對每個人的列表求值而對Map選擇標準是針對每一個映射項(Java類型Map.Entry對象)求值,而評價。Map入口有其如屬性的可訪問的鍵和值供選擇使用。 

這個表達式將返回一個新的Map,其元素由原始Map中項的值小於27的元素組成。

 

    除了返回所有被選擇的元素,也可以檢索第一個和最後一個值。用^[…]獲得第一個匹配入口,用$[…]獲得最後一個匹配入口。

集合投影

投影允許集合驅動子表達式的求值,其結果是一個新的集合。對於投影語法![projectionExpression]。最容易理解的例子,假設我們有一個發明者列表,但要在城市名單中尋找他們在那裏出生。我們要對發明者列表中每項有效地求出‘placeOfBirth.city'。使用投影:

 

    Map也可以用於驅動投影,這時投影表達式對Map中的每個項目求值(作爲一個Java Map.Entry表示)。跨越Map投影的結果是對每個Map入口投影表達式求值後組成的列表。

表達式模板

    表達式模板允許與一個或多個求值塊複合文字文本。每個求值塊有可自定義的前綴和後綴的字符定界,一個普遍的選擇是使用的分隔符$()定界。例如,

 

    該字符串的求值是通過連接文字文本的‘random number is’和$()定界符內求值表達式的結果,在這裏是調用的random()方法的結果。parseExpression()方法的第二個參數是ParserContext的類型。該ParserContext接口通常影響表達式如何被解析以支持模板功能。在TemplatedParserContext的定義如下所示。

 

6.6 示例中使用的類

Inventor.java

 

PlaceOfBirth.java

   

Society.java

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章