Spring框架學習之高級依賴關係配置(二)

     緊接着上篇內容,本篇文章將主要介紹XML Schema的簡化配置和使用SpEL表達式語言來優化我們的配置文件。

一、基於XML Schema的簡化配置方式
從Spring2.0以來,Spring支持使用XML Schema來簡化配置。在以前的bean元素配置下,所有的屬性注入都需要一個property元素,集合屬性就需要更多的這樣的元素,一旦項目龐大,整個配置文件將無法維護。XML Schema提供的命名空間,可以幫助我們的配置文件縮減容量。主要有三種命名空間:

  • p:命名空間簡化屬性配置
  • c:命名空間簡化構造配置
  • util:命名空間簡化集合配置

1、使用p:命名空間簡化配置
首先看一個我們常見的bean的配置:

<bean id="person" class="MyPackage.Person">
    <property name="name" value="single"/>
    <property name="age" value="22"/>
</bean>

這是一個再普通不過的bean的配置,它等效於:

<bean id="person" class="MyPackage.Person" p:name="single" p:age="22" />

但是這麼做的前提是,在Spring配置文件的XML頭部導入p的命名空間:

xmlns:p="http://www.springframework.org/schema/p"

無論你是使用IDE自動導入的,還是使用工具,或者自己手動導入的,想要使用p Schema,就必須該命名空間。p是property的縮寫,除了可以注入普通的值類型之外,還可以注入引用類型,例如:

<bean id="person" class="MyPackage.Person" p:name-ref="stuName" p:age="22" />

2、使用c:命名空間簡化配置
我們使用p命名空間簡化了設置注入操作,c命名空間則是constructor的縮寫,它用於簡化構造注入的操作。例如:

<bean id="person" class="MyPackage.Person" c:name="single" c:age="22" />

Spring最後會調用構造注入,將name和age作爲參數出入bean類的構造器中,構造實例返回。除此之外,還可以這麼寫:

<bean id="person" class="MyPackage.Person" c:_0="single" c:_1="22" />

下劃線加上數字表示,這是構造器中的第幾個參數,到時候會被Spring按序傳入構造器中。

3、使用util命名空間簡化配置
util給我們提供了以下幾個元素:

  • constant:對於在配置文件中獲取指定類的靜態Field的值的一個簡化配置
  • property-path:對於在配置文件中獲取調用getter方法的一個簡化配置
  • list:簡化list作爲bean的配置
  • map:簡化map作爲bean的配置
  • set:簡化set作爲bean的配置
  • properties:加載一份properties屬性文件

^1、constant
首先看一段我們之前用於獲取一個類的靜態屬性的配置:

<bean id="person" class="MyPackage.Person">
    <property name="name" value="single"/>
    <property name="age">
        <bean class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
            <property name="targetClass" value="MyPackage.BeanStaticClass"/>
            <property name="targetField" value="age"/>
        </bean>
    </property>
</bean>

這是一段我們之前用於在配置文件中獲取類靜態屬性的代碼,總體上來說還是挺繁瑣的,下面我們使用util下的constant來簡化這段配置。

<bean id="person" class="MyPackage.Person">
    <property name="name" value="single"/>
    <property name="age">
        <util:constant static-field="MyPackage.BeanStaticClass.age"/>
    </property>
</bean>

static-field屬性的值指定了需要訪問那個類下的那個靜態屬性。如果需要將該值單獨定義在容器中,可以爲其增加id屬性以便其他bean實例獲取。

^2、property-path
對於在配置文件中直接調用其他bean的getter方法,我們一般如是配置:

<bean id="student" class="MyPackage.Student">
    <property name="age" value="22"/>
</bean>

<bean id="person" class="MyPackage.Person">
    <property name="name" value="single"/>
    <property name="age">
        <bean class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
            <property name="targetBeanName" value="student"/>
            <property name="propertyPath" value="age"/>
        </bean>
    </property>
</bean>

一般我們需要這麼寫來配置,下面我們通過util的property-path來簡化配置:

<bean id="student" class="MyPackage.Student">
    <property name="age" value="22"/>
</bean>

<bean id="person" class="MyPackage.Person">
    <property name="name" value="single"/>
    <property name="age">
        <util:property-path path="student.age"/>
    </property>
</bean>

property-path的值指定了需要調用那個bean實例的那個getter方法。如果需要單獨將該值配置在容器中,可以爲其指定id。

^3、list
通過util,Spring允許我們單獨定義一個list bean在容器中。一個list bean給我們提供如下幾個屬性:

  • id:容器中的唯一標識
  • list-class:指定實現該list的實現類,默認爲ArrayList
  • scope:指定該list的作用域

下面我們定義一個list bean:

<util:list id="list" list-class="java.util.ArrayList">
    <value>nanjing</value>
    <value>nantong</value>
    <value>yancheng</value>
</util:list>

^4、map和set
有關map和set的util使用,基本和list的使用情況類似,此處只給出創建bean的配置代碼,其他的不再贅述。

//map
<util:map id="map" map-class="java.util.HashMap">
    <entry key="中國銀行" value="241241212" />
   <entry key="建設銀行" value="543534545"/>
</util:map>
//set
<util:set id="set" set-class="java.util.HashSet">
    <value>single</value>
    <value>cyy</value>
</util:set>

至此,有關XML Schema的基本內容已如上述所述,Spring中還有一些其他相關的Schema文件,它們各自有各自的作用,有用於簡化AOP配置的,有用於簡化事務配置的等等,我們將在後續文章中進行學習。

二、使用Spring的EL表達式語言
Spring的配置文件有一個非常明顯的缺陷,大量的靜態注入,動態性不強。而SpEL類似於jsp的EL,採用表達式的方式爲屬性注入值,當程序動態運行時,這些表達式的值才確定。SpEL可以單獨使用,也可以在Spring配置文件中使用,我們此處主要介紹在配置文件中的SpEL的使用。

1、創建數組
有時我們的實例中有類型爲數組的屬性,那麼我們就可以通過SpEL定義數組作爲參數注入依賴給該屬性。

<bean id="person" class="MyPackage.Person">
    <property name="array" value="#{new int[]{12,2,5,7,8,6,8}}" />
</bean>

在Spring配置中使用SpEL中,基本的使用格式如下:

#{expression}

2、創建list集合
我們也可以使用SpEL定義list集合,例如:

<bean id="person" class="MyPackage.Person">
    <property name="list" value="#{{'single','cyy','xijingping'}}"/>
</bean>

list集合的定義使用 “{….}”,大括號中的每個元素都對應於list中的一個元素。

我們可以通過以下語法格式訪問list中的元素:

listName[index]

訪問容器中map集合中的元素:

mapName[key]

例如:

<bean id="person" class="MyPackage.Person">
    <property name="name" value="#{list[0]}"/>
</bean>

這段配置會向person實例中的name屬性注入容器中已經定義好的名爲list的第一個元素的值。

3、調用方法
在SpEL中調用任意方法將會比我們之前介紹的那種純配置形式簡單很多,例如:

<bean id="person" class="MyPackage.Person">
    <property name="name" value="#{'hello'.concat(' world!')}"/>
</bean>

我們這裏調用了jdk中的方法爲person實例的name屬性注入依賴值,當然也可以是我們自己定義的方法,可以是任意的方法。

4、類運算符
SpEL提供了一種運算符:T()。該運算符告訴Spring將括號中的內容作爲一類類型而不是作爲字符串進行解析。例如:

<bean id="person" class="MyPackage.Person">
    <property name="name" value="#{java.lang.Math.random()}"/>
</bean>

這樣書寫,Java會給我們報錯,說java.lang.Math.random()並不是一個字符串,但是如果給他加上單引號,那麼該函數就會以純字符串作爲參數注入給name屬性,並不會被識別爲正常函數。

正確書寫格式如下:

<bean id="person" class="MyPackage.Person">
    <property name="name" value="#{T(java.lang.Math).random()}"/>
</bean>

5、集合選擇
使用SpEL集合選擇的基本格式如下:

collection.?[condition_expr]

只有符合條件condition_expr的集合元素纔會被選擇出來,例如:

<bean id="person" class="MyPackage.Person">
    <property name="list" value="#{list.?[length()>7]}"/>
</bean>

Spring會遍歷整個list,每個元素都會調用他的length方法判斷是否大於7,如果不是將捨棄該元素,否則該元素纔會被帥選出來。

6、集合投影
集合投影可以讓集合中的每個元素都去執行同一個方法,每個元素調用同一個方法,不同元素的該方法的返回值將構成最終的新集合。例如:

<bean id="person" class="MyPackage.Person">
    <property name="list" value="#{list.![length()]}"/>
</bean>

最終新集合中的元素是原集合中每個元素的長度。

SpEL的用法遠非如此,這裏只是列舉了常用的幾種用法。

兩篇文章加強了對bean配置的理解,有總結不到之處,望指出!

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