在這篇文章裏,對於Spring XML的配置,我將向你展現12種比較好的實踐。其中的一些實踐不只是好的實踐,更是必要的實踐。除此之外,還有其餘因素,例如領域模型的設計,都能影響XML的配置,可是這篇文章重點研究XML配置的易讀性和易管理性。
1。不要使用autowiring
Spring能夠經過類的自省來自動綁定其依賴部分,使得你沒必要明確指明bean的屬性和構造器。Bean的屬性能夠經過屬性名稱或類型匹配來實現自動綁定。構造器經過類型匹配來實現自動綁定。你甚至能夠指定自動檢測自動綁定模式,它能夠引導Spring選擇一種適當的運行機制。先來看看下面的一個例子:
<bean id="orderService" class="com.lizjason.spring.OrderService" autowire="byName"/>
OrderService類的屬性名在容器中用於匹配bean實例。自動綁定能夠潛在地節省一些打字和減小一些混亂。可是在現實世界的工程裏你不該該使用這種方式,這是由於它犧牲了配置的清晰性和可維護性。許多指南和介紹中大量吹捧自動綁定是Spring的一種極好的特徵而沒有提到這一特性所帶來的犧牲。依個人觀點,這就像Spring中的object-pooling,它更像是一種爲了佔據更多市場的商業特徵。它對於XML配置文件的小巧化是一個好辦法,但實際上也增長了複雜程度,尤爲當你運行有大量類聲明的工程時。雖然Spring容許你混合自動綁定和手動綁定,可是這個矛盾會使XML配置更加晦澀難懂。
2.使用通俗的命名
這個方式對於Java編碼也同樣適用。在工程中使用清晰的、描述性的、協調的通俗名稱對於開發者理解XML配置是十分有益的。例如對於bean ID,你能夠根據通俗的Java類名來命名它。對於例子中OrderServiceDAO的bean ID命名爲orderServiceDAO。對於大的工程,你能夠在bean ID前面加上包名做爲前綴。
3. 使用簡潔的形式
簡潔形式避免了冗長,是由於它從子元素中將屬性值和參考寫到屬性中。例以下面的例子:
<bean id="orderService" class="com.lizjason.spring.OrderService">
<property name="companyName">
<value>lizjason</value>
</property>
<constructor-arg>
<ref bean="orderDAO">
</constructor-arg>
</bean>
可使用簡潔形式將上述代碼重寫爲:
<bean id="orderService" class="com.lizjason.spring.OrderService">
<property name="companyName" value="lizjason"/>
<constructor-arg ref="orderDAO"/>
</bean>
簡潔形式功能在1.2版本中可使用。對於<ref local="...">沒有簡潔形式。
簡潔形式不但能夠節約你的打字,並且可使XML配置文件清晰。它最引人注目的是當在一個配置文件中有大量定義的類時能夠提升易讀性。
4. 對於構造器參數匹配,類型名比序號好。
當一個構造器含有一個以上的同種類型的參數,或者屬性值的標籤已經被佔用時,Spring容許你使用從0計數的序號來解決這些會帶來混淆的問題。例如:
<bean id="billingService" class="com.lizjason.spring.BillingService">
<constructor-arg index="0" value="lizjason"/>
<constructor-arg index="1" value="100"/>
</bean>
像下面這樣,利用類型屬性來編寫會更好一些:
<bean id="billingService" class="com.lizjason.spring.BillingService">
<constructor-arg type="java.lang.String" value="lizjason"/>
<constructor-arg type="int" value="100"/>
</bean>
使用索引能夠稍稍減小一些冗長,可是和使用類型屬性相比,它仍是有容易發生錯誤的傾向和難於閱讀的缺點。你應該只在構造器參數不明確的時候,才使用索引這一方法。
5. 儘量重用已定義過的bean
Spring提供一種相似繼承同樣的機制來減小配置信息的複製並簡化XML配置。定義一個子類能夠從它父類那裏繼承配置信息,而父類實質上做爲子類的一個模板。這就是大工程中所謂的重用。你所須要作的就是在父類bean中設置abstract=true,而後在子bean註明它本身的父類bean。例如:
<bean id="abstractService" abstract="true" class="com.lizjason.spring.AbstractService">
<property name="companyName" value="lizjason"/>
</bean>
<bean id="shippingService" parent="abstractService" class="com.lizjason.spring.ShippingService">
<property name="shippedBy" value="lizjason"/>
</bean>
ShippingService類從abstractService類那裏繼承companyName屬性的值——lizjason。若是你沒有爲一個bean指明類或factory方法,那麼這個bean即是抽象的。
6. 儘可能使用ApplicationContext來裝配定義的bean
像在Ant腳本中的引用同樣,Spring的引用對於裝配模塊化的bean來講是頗有用的。例如:
<beans>
<import resource="billingServices.xml"/>
<import resource="shippingServices.xml"/>
<bean id="orderService" class="com.lizjason.spring.OrderService"/>
<beans>
相對於使用import在XML配置中來預裝配,經過ApplicationContext來配置這些beans,顯得更加靈活。利用ApplicationContext也使得XML配置易於管理。你能夠像下面的例子那樣在ApplictionContext構造器里布置bean:
String[] serviceResources = {"orderServices.xml", "billingServices.xml","shippingServices.xml"};
ApplicationContext orderServiceContext = new ClassPathXmlApplicationContext(serviceResources);
7. 利用id做爲bean的標識符
你能夠指定一個id或名稱來做爲bean的標識符。雖然使用id不會提升易讀性,可是它可讓XML parser對bean的引用有效方面進行更好的驗證。若是因爲XML IDREF的限制而不能使用某個id,你能夠利用names來做爲bean的標識符。XML IDREF的限制是id必須以字母開頭(或者在XML規範中定義的標點符號),後面接着字母,數字,連字號,下劃線,冒號等。實際上,遇到XML IDREF限制的問題是不多見的。
8. 在開發階段使用依賴檢驗
你能夠在bean中給依賴檢驗的屬性設置值,而不採用原先默認的空值,屬性設置例如simple,object或all,以便容器進行依賴檢驗。當bean的所有的屬性(或某類屬性)須要被明確設置或自動綁定時,依賴檢驗便顯得頗有用。
<bean id="orderService" class="com.lizjason.spring.OrderService" dependency-check="objects">
<property name="companyName" value="lizjason"/>
<constructor-arg ref="orderDAO"/>
</bean>
在這個例子裏,容器確保爲orderService bean設置的屬性不是primitives 或者 collections。爲全部的bean設置默認依賴檢測也是能夠的,可是咱們不多這樣作,是由於有些bean的屬性根本就沒必要設置。
9. 爲每一個配置文件加上一個header comment
最好使用descriptive id和名稱來代替在XML配置文件中的註釋。此外,加上一個配置文件header也頗有用處,它能夠概述文件中所定義的bean。你能夠選擇將描述內容加入description標籤中。例如:
<beans>
<description>
This file defines billing service related beans and it depends on baseServices.xml,which provides
service bean templates...
</description>
...
</beans>
使用description標籤的一個好處是能夠容易地利用工具從標籤中選取出description(的內容)。
10. 對於任何變化,要與隊友積極交流
當你重構Java代碼時,你須要隨時更新配置文件而且通知隊友。XML配置文件也是代碼,它們是應用程序的相當重要的部分,可是它們難於閱讀和維護。大部分時間你既要閱讀XML配置文件又要閱讀運行中的Java代碼。
11. Setter injection優於constructor injection
Spring提供3種類型的依賴注入: constructor injection,setter injection, 和method injection。咱們通常只用前兩種類型。
<bean id="orderService" class="com.lizjason.spring.OrderService">
<constructor-arg ref="orderDAO"/>
</bean>
<bean id="billingService" class="com.lizjason.spring.BillingService">
<property name="billingDAO" ref="billingDAO">
</bean>
這個例子中,orderService類使用的是constructor injection,而BillingService類使用的是setter injection。constructor injection能夠確保bean不會在一個非法狀態下被建立,可是setter injection更加靈活而且更易管理,尤爲當類存在不少屬性而且其中一些是可選的狀況下。
12. 不要濫用依賴注入
做爲最後一點,Spring ApplicationContext能夠替你建立Java對象,可是並非全部的Java對象都經過依賴注入來建立的。例如,全局的對象不該該經過ApplicationContext來建立。Spring是一個很棒的框架,可是,就易讀性和易管理性而言,當定義大量bean的時候,基於XML的配置問題就會突出。過分的依賴注入會使XML配置變得複雜並且臃腫。記住!使用強大的IDE時,例如Eclipse和IntelliJ,與XML文件相比,Java代碼更加易讀,易維護,易管理。
總結 對於Spring的配置,XML是很優秀的方式。但當定義大量bean時,基於XML配置會變得冗長,笨拙。Spring提供了豐富的配置選項。適當地利用其中的選項可使XML配置清晰,可是,有些選項,例如autowiring(自動綁定),每每會下降易讀性和易維護性。文章中所列舉的實例,能夠幫助你建立出清晰易讀的XML配置文件。