|
Spring是一個強大的Java應用框架,它廣泛地應用于Java應用程序中,為Plain Old Java Objects(POJO)提供企業(yè)級服務。Spring利用依賴注入機制來簡化工作,同時提高可測試性。其配置文件(通常是XML格式)中指定了Spring bean、依賴性以及bean所需的服務。但是,這些XML配置文件既冗長又不實用。對于需要定義大量Spring bean的大型項目來說,它們難以閱讀和管理。 在本文中,我將向您展示12種用于Spring XML配置的最佳實踐。其中的一些實踐與其說是最佳實踐,倒不如說是必要實踐。注意,其他因素(如域模型的設置)也可能影響XML的配置,但是本文重點研究XML配置的可讀性和可管理性。 1。避免使用自動綁定(autowiring)功能 Spring可以通過bean類的自省自動綁定依賴性,所以不必顯式指明bean的屬性和構造函數。Bean屬性可以通過屬性名稱或類型匹配來實現自動綁定。構造函數通過類型匹配來實現自動綁定。甚至可以指定自動檢測autowiring模式,它可以引導Spring選擇一種適當的運行機制。先來看看下面的一個例子: <bean id="orderService" class="com.lizjason.spring.OrderService" autowire="byName"/> OrderService類的屬性名在容器中用于匹配bean實例。自動綁定可能會節(jié)省一些鍵入工作量并減少混亂。但是在現實項目中不應該使用這種方式,因為它犧牲了配置的可讀性和可維護性。許多指南和介紹中大肆吹捧自動綁定是Spring的一項極好的特性,而沒有提到這一特性所帶來的犧牲。依我來看,這就像Spring中的對象池(object-pooling),更大程度上只是宣傳的噱頭。對于精簡XML配置文件來說,它是一個好辦法,但它實際上增加了復雜性,尤其是在運行包含大量類聲明的項目時。雖然Spring允許混合使用自動綁定和顯式綁定,但這會使XML配置更加晦澀難懂。 2.使用命名約定 該原則對于Java編碼也一樣適用。在項目中使用清晰的、描述性的、一致的命名約定將非常有利于開發(fā)人員理解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="...">,沒有簡潔形式。 簡潔形式不但可以節(jié)約鍵入工作量,而且可以使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> 利用type屬性來編寫會更好一些,如下: <bean id="billingService" class="com.lizjason.spring.BillingService"> <constructor-arg type="java.lang.String" value="lizjason"/> <constructor-arg type="int" value="100"/> </bean> 使用index可以減少一些代碼,但是與type屬性相比,它更易于出錯且難于閱讀。只有在構造函數參數不明確的時候,才應該使用index。 5. 盡可能重用已定義的bean Spring提供了一種類似于繼承的機制來減少配置信息的復制并簡化XML配置。定義一個子類,它就可以從父類那里繼承配置信息,而父類實際上成為子類的一個模板。這就是大型項目中所謂的重用。只需在父類bean中設置abstract=true,然后在子bean中指定parent引用。例如: <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沒有指定類或工廠方法,那么這個bean便是抽象的。 6. 在導入時,首選通過ApplicationContext來匯編bean定義 像Ant腳本中的導入一樣,Spring的import元素對于匯編模塊化的bean定義來說是很有用的。例如: <beans> <import resource="billingServices.xml"/> <import resource="shippingServices.xml"/> <bean id="orderService" class="com.lizjason.spring.OrderService"/> <beans> 然而,相對于使用import在XML配置中進行預匯編,通過ApplicationContext來配置這些bean則顯得更加靈活。使用ApplicationContext的話,XML配置也更易于管理??梢韵駻pplictionContext構造函數傳遞一組bean定義,如下: String[] serviceResources = {"orderServices.xml", "billingServices.xml", "shippingServices.xml"}; ApplicationContext orderServiceContext = new ClassPathXmlApplicationContext(serviceResources); 7. 使用id作為bean標識符 可以指定一個id或名稱來作為bean標識符。雖然使用id不能提高可讀性,但是它可以利用XML分析程序來對bean引用進行驗證。如果由于XML IDREF的約束而不能使用某個id,那么可以使用名稱來作為bean的標識符。XML IDREF的約束是:id必須以字母(或者XML規(guī)范中定義的標點符號)開頭,后面是字母、數字、連字符、下劃線、冒號或句點。實際上,很少會遇到XML IDREF約束問題。 8. 在開發(fā)階段使用依賴性檢查(dependency-check) 可以在bean定義中為dependency-check屬性設置一個非默認值,比如simple、objects或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. 為每個配置文件添加首部注釋 最好使用描述性的id和名稱來取代XML配置文件中的內置注釋。此外,添加一個配置文件首部也很有用,它可以概述文件中所定義的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標簽的一個好處是可以輕松地利用工具從標簽中選獲取描述內容。 10. 對于更改,團隊成員要積極交流 在重構Java代碼時,需要隨時更新配置文件并通知團隊成員。XML配置文件也是代碼,它們是應用程序的至關重要的部分,但是它們難于閱讀和維護。大部分情況下,需要同時閱讀XML配置文件和運行中的Java代碼。 11. Setter注入優(yōu)于構造函數注入 Spring提供了3種類型的依賴注入:構造函數注入(constructor injection)、setter注入(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類使用的是構造函數注入,而BillingService類使用的是setter注入。構造函數注入可以確保bean不會在一個非法狀態(tài)下被創(chuàng)建,但是setter注入更加靈活且更易于管理,尤其是在類包含許多屬性并且其中一些可選的情況下。 12. 不要濫用依賴注入 最后一點,Spring ApplicationContext可以為您創(chuàng)建Java對象,但并不是所有的Java對象都應通過依賴注入來創(chuàng)建。例如,全局對象不應該通過ApplicationContext來創(chuàng)建。Spring是一個很棒的框架,但是,就可讀性和易管理性而言,如果定義了大量bean,基于XML的配置就可能成為問題。過度使用依賴注入會使XML配置變得復雜且臃腫。要知道,借助于功能強大的IDE(如Eclipse和IntelliJ),Java代碼比XML文件更加易讀、易維護、易管理。 結束語 XML是通用的Spring配置方式。但如果定義了大量bean,基于XML的配置就會變得冗長而不實用。Spring提供了豐富的配置選項,恰當地利用其中的選項可以使XML配置更清晰,但是,有些選項(如autowiring)往往會降低配置文件的可讀性和可維護性。遵循本文中所描述的最佳實踐,將有助于您創(chuàng)建出清晰易讀的XML配置文件。 |
|
|