spring實戰(2)--高級裝配

一、profile

1、@Profile:應用在類級別上告訴Spring這個配置類中的bean只有在此profile激活時纔會創建。在Spring 3.1中,只能在類級別上使用@Profile註解。從Spring 3.2開始,你也可以在方法級別上使用@Profile註解,與@Bean註解一同使用。沒有指定profile的bean始終都會被創建,與激活哪個profile沒有關係。

2、xml中在中增加屬性profile:在根元素中嵌套定義元素,而不是爲每個環境都創建一個profile XML文件。這能夠將所有的profile bean定義放到同一個XML文件中,同時增加該屬性。

3、@ActiveProfiles:Spring提供了@ActiveProfiles註解,我們可以使用它來指定運行測試時要激活哪個profile。在集成測試時,通常想要激活的是開發環境的profile。

二、條件化的bean

1、@Conditional:Spring 4引入了一個新的@Conditional註解,它可以用到帶有@Bean註解的方法上。如果給定的條件計算結果爲true,就會創建這個bean,否則的話,這個bean會被忽略。 @Conditional將會通過Condition接口進行條件對比,設置給@Conditional的類可以是任意實現了Condition接口的類型。

三、自動裝配歧義性

1、@Primary:在Spring中,可以通過@Primary來表達最喜歡的方案。@Primary能夠與@Component組合用在組件掃描的bean上,也可以與@Bean組合用在Java配置的bean聲明中。如果你使用XML配置bean的話,同樣可以實現這樣的功能。元素有一個primary屬性用來指定首選的bean。只能標示一個優先的可選方案。

2、@Qualifier:Spring的限定符能夠在所有可選的bean上進行縮小範圍的操作,最終能夠達到只有一個bean滿足所規定的限制條件。@Qualifier是使用限定符的主要方式。它可以與@Autowired和@Inject協同使用,在注入的時候指定想要注入進去的是哪個bean。

3、創建自定義的限定符:可以爲bean設置自己的限定符,而不是依賴於將bean ID作爲限定符。在這裏所需要做的就是在bean聲明上添加@Qualifier註解。它可以與@Component組合使用。當通過Java配置顯式定義bean的時候,@Qualifier也可以與@Bean註解一起使用。當使用自定義的@Qualifier值時,最佳實踐是爲bean選擇特徵性或描述性的術語,而不是使用隨意的名字。

4、使用自定義的限定符註解:可以創建自定義的限定符註解,藉助這樣的註解來表達bean所希望限定的特性。這裏所需要做的就是創建一個註解,它本身要使用@Qualifier註解來標註。這樣我們將不再使用@Qualifier(“cold”),而是使用自定義的@Cold註解。通過在定義時添加@Qualifier註解,它們就具有了@Qualifier註解的特性。它們本身實際上就成爲了限定符註解。通過聲明自定義的限定符註解,我們可以同時使用多個限定符,不會再有Java編譯器的限制或錯誤。與此同時,相對於使用原始的@Qualifier並藉助String類型來指定限定符,自定義的註解也更爲類型安全。

四、bean的作用域

1、Spring定義了多種作用域,可以基於這些作用域創建bean,包括:單例(Singleton):在整個應用中,只創建bean的一個實例。原型(Prototype):每次注入或者通過Spring應用上下文獲取的時候,都會創建一個新的bean實例。會話(Session):在Web應用中,爲每個會話創建一個bean實例。請求(Rquest):在Web應用中,爲每個請求創建一個bean實例。

2、@Scope:單例是默認的作用域,但是正如之前所述,對於易變的類型,這並不合適。如果選擇其他的作用域,要使用@Scope註解,它可以與@Component或@Bean一起使用。使用ConfigurableBeanFactory類的SCOPE_PROTOTYPE常量設置了原型作用域。

3、scope屬性:如果你使用XML來配置bean的話,可以使用元素的scope屬性來設置作用域。

4、會話作用域:就購物車bean來說,會話作用域是最爲合適的,因爲它與給定的用戶關聯性最大。要指定會話作用域,我們可以使用@Scope註解,它的使用方式與指定原型作用域是相同的。

(1)@Scope的value屬性:我們將value設置成了WebApplicationContext中的SCOPE_SESSION常量(它的值是session)。這會告訴Spring爲Web應用中的每個會話創建一個ShoppingCart。這會創建多個ShoppingCart bean的實例,但是對於給定的會話只會創建一個實例,在當前會話相關的操作中,這個bean實際上相當於單例的。@Scope同時還有一個proxyMode屬性,它被設置成了ScopedProxyMode.INTERFACES。這個屬性解決了將會話或請求作用域的bean注入到單例bean中所遇到的問題。

(2)@Scope的proxyMode屬性:被設置成了ScopedProxyMode.INTERFACES,這表明這個代理要實現ShoppingCart接口,並將調用委託給實現bean。如果bean類型是具體類的話,我們必須要將proxyMode屬性設置爲ScopedProxyMode.TARGET_CLASS,以此來表明要以生成目標類擴展的方式創建代理。請求作用域的bean會面臨相同的裝配問題。因此,請求作用域的bean應該也以作用域代理的方式進行注入。

5、XML來聲明會話或請求作用域的bean:元素的scope屬性能夠設置bean的作用域,要設置代理模式,我們需要使用Spring aop命名空間的一個新元素。aop:scoped-proxy是與@Scope註解的proxyMode屬性功能相同的Spring XML配置元素。它會告訴Spring爲bean創建一個作用域代理。默認情況下,它會使用CGLib創建目標類的代理。但是我們也可以將proxy-target-class屬性設置爲false,進而要求它生成基於接口的代理。必須在XML配置中聲明Spring的aop命名空間。

五、運行時值注入

1、值注入:依賴注入是將一個bean引用注入到另一個bean的屬性或構造器參數中。它通常來講指的是將一個對象與另一個對象進行關聯。bean裝配的另外一個方面指的是將一個值注入到bean的屬性或者構造器參數中。硬編碼是可以的,但有的時候,會希望避免硬編碼值,而是想讓這些值在運行時再確定。爲了實現這些功能,Spring提供了兩種在運行時求值的方式:

(1)屬性佔位符(Property placeholder)。

(2)Spring表達式語言(SpEL)。

2、@PropertySource:在Spring中,處理外部值的最簡單方式就是聲明屬性源並通過Spring的Environment來檢索屬性。@PropertySource引用了類路徑中一個名爲app.properties的文件。這個屬性文件會加載到Spring的Environment中,稍後可以從這裏檢索屬性。

3、Spring的Environment:getProperty()方法並不是獲取屬性值的唯一方法,getProperty()方法有四個重載的變種形式。Environment還提供了幾個與屬性相關的方法,如果你在使用getProperty()方法的時候沒有指定默認值,並且這個屬性沒有定義的話,獲取到的值是null。如果你希望這個屬性必須要定義,那麼可以使用getRequiredProperty()方法。如果想檢查一下某個屬性是否存在的話,那麼可以調用Environment的containsProperty()方法。如果想將屬性解析爲類的話,可以使用getPropertyAsClass()方法。除了屬性相關的功能以外,Environment還提供了一些方法來檢查哪些profile處於激活狀態。

4、解析屬性佔位符:Spring一直支持將屬性定義到外部的屬性的文件中,並使用佔位符值將其插入到Spring bean中。在Spring裝配中,佔位符的形式爲使用“${ … }”包裝的屬性名稱。如果我們依賴於組件掃描和自動裝配來創建和初始化應用組件的話,那麼就沒有指定佔位符的配置文件或類了。在這種情況下,我們可以使用@Value註解,它的使用方式與@Autowired註解非常相似。爲了使用佔位符,我們必須要配置一個PropertyPlaceholderConfigurer bean或PropertySourcesPlaceholderConfigurer bean。從Spring 3.1開始,推薦使用PropertySourcesPlaceholderConfigurer,因爲它能夠基於Spring Environment及其屬性源來解析佔位符。如果你想使用XML配置的話,Spring context命名空間中的context:propertyplaceholder元素將會爲你生成PropertySourcesPlaceholderConfigurer bean。

5、使用Spring表達式語言進行裝配:Spring 3引入了Spring表達式語言(Spring Expression Language,SpEL),它能夠以一種強大和簡潔的方式將值裝配到bean屬性和構造器參數中,在這個過程中所使用的表達式會在運行時計算得到值。SpEL擁有很多特性,包括:

(1)使用bean的ID來引用bean;

(2)調用方法和訪問對象的屬性;

(3)對值進行算術、關係和邏輯運算;

(4)正則表達式匹配;

(5)集合操作。

6、SpEL樣例:

(1)SpEL表達式要放到“#{ … }”之中。T()表達式會將java.lang.System視爲Java中對應的類型,因此可以調用其static修飾的currentTimeMillis()方法。

(2)在bean裝配的時候使用這些表達式。可以使用@Value註解,這與之前看到的屬性佔位符非常類似。在這裏我們所使用的不是佔位符表達式,而是SpEL表達式。在XML配置中,你可以將SpEL表達式傳入或的value屬性中,或者將其作爲p-命名空間或c-命名空間條目的值。

(3)引用bean、屬性和方法:SpEL所能做的另外一件基礎的事情就是通過ID引用其他的bean。除了引用bean的屬性,我們還可以調用bean上的方法。爲了避免出現NullPointerException,我們可以使用類型安全的運算符“?.”,這個運算符能夠在訪問它右邊的內容之前,確保它所對應的元素不是null。

(4)在表達式中使用類型:如果要在SpEL中訪問類作用域的方法和常量的話,要依賴T()這個關鍵的運算符。

(5)SpEL運算符:SpEL提供了多個運算符,這些運算符可以用在SpEL表達式的值上。當使用String類型的值時,“+”運算符執行的是連接操作,與在Java中是一樣的。SpEL同時還提供了比較運算符,用來在表達式中對值進行對比。比較運算符有兩種形式:符號形式和文本形式。在大多數情況下,符號運算符與對應的文本運算符作用是相同的,使用哪一種形式均可以。SpEL還提供了三元運算符(ternary),它與Java中的三元運算符非常類似。

(6)計算正則表達式:SpEL通過matches運算符支持表達式中的模式匹配。matches運算符對String類型的文本(作爲左邊參數)應用正則表達式(作爲右邊參數)。matches的運算結果會返回一個Boolean類型的值:如果與正則表達式相匹配,則返回true;否則返回false。

(7)計算集合:“[]”運算符用來從集合或數組中按照索引獲取元素,實際上,它還可以從String中獲取一個字符。SpEL還提供了查詢運算符(.?[]),它會用來對集合進行過濾,得到集合的一個子集。SpEL還提供了另外兩個查詢運算符:“.1”和“.$[]”,它們分別用來在集合中查詢第一個匹配項和最後一個匹配項。SpEL還提供了投影運算符(.![]),它會從集合的每個成員中選擇特定的屬性放到另外一個集合中。


  1. ↩︎

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