Spring入門以及Spring優點

15年前6月的一個悶熱的早晨,我爬到一艘老式的玻璃纖維皮划艇中。它是如此古老,以至於有些小碎片差點插到了我的手指中,而且划槳長度大約是傳統激流划槳的兩倍。我游泳的時候要多過划船,但是這沒有關係。15年之後,我仍然對它着迷。

  大約2年前,我試用了在Hibernate站點上突出提到的Spring項目。我覺得它就像是上面提到的老式皮划艇:它再適合我不過了。爲了進行企業硬編碼,Spring如此深植於我的編程工作中,以至於我使用它作爲我第4本Java著作《Spring: A Developer's Notebook》的主題。在本文中,我將說明其中的原因。

  1.Spring 提供更好的優勢

  在河流中,我學會了更多地使用我的腰和背來划槳,因爲我的手臂肌肉無法堅持整日在河上划槳。我變得更加高效;我獲得了更好的利用率。藉助於Spring,我可以使每行代碼做更多的事情。藉助於Spring,您可以發現很多額外的手段,其中最大的一處是在持久性方面。下面給出一個Hibernate數據訪問對象中的方法:

  public List getReservations( ) {return getHibernateTemplate( ).find("from Reservation");}}

  注意您沒有看到的內容。這裏沒有事務處理。Spring允許構建配置代碼來處理事務。不必通過關閉會話來管理資源。不必進行自己的配置。不必在這個層次上管理異常,因爲異常是未經檢查的。可以自由地在最合適的位置管理它們。下面給出了另一個Hibernate方法,沒有使用Spring:

  public List getBikesOldWay( ) throws Exception {List bikes = null;Session s = null;try {s = mySessionFactory.openSession( );bikes = s.find("from Bike");}catch (Exception ex) {//handle exception gracefully}finally {s.close( );}return bikes;

  Spring爲您提供了更好的優勢。藉助於Spring,可以更快地編寫代碼,而進行更少的維護。

  2.Spring支持POJO編程

  EJB 2.x失敗之後,我們都在尋求表達企業服務而不使用笨拙的模型侵入每個bean的方法。當然,我們需要事務、安全性、持久性,有時還需要遠程控制。對於EJB,我必須學習一個廣泛使用的API,並通過新的工具和部署流程開展工作。我是容器所提供的服務的奴隸。而藉助於Spring,我可以選擇自己的服務和持久性框架。我進行POJO編程,並使用配置文件爲它們添加企業服務。

  在《Spring: A Developer's Notebook》一書中,我構建了一個RentaBike應用程序。我把我的POJO稱作hibRentaBike,而不是會話bean或實體bean;它用作我的數據訪問對象。我還在別處添加了服務。Spring配置文件稱爲context,它是一個XML文件,包含容器中所有的bean以及bean所需的屬性和服務。下面讓我們看一看。

  目標:

Bruce's Bikes

  攔截器:

  com.springbook.RentABike.transferReservation=PROPAGATION_REQUIRED,-ReservationTransferExceptioncom.springbook.RentABike.save*=PROPAGATION_REQUIREDcom.springbook.RentABike.*=PROPAGATION_REQUIRED,readOnly

  代理:

  com.springbook.RentABiketransactionInterceptor,rentaBikeTarget

  注意,有3種不同的bean:代理、目標和攔截器。代理將調用POJO以及POJO所需的任何服務。攔截器包含用於調用服務的結合代碼(glue code),還指定了如何處理目標中的每個方法。任何需要訪問RentaBike的人都要調用代理,而代理調用事務攔截器,然後事務攔截器就會開始一個事務並調用目標(POJO)。目標完成自己的工作,返回給(負責提交事務的)攔截器,然後再返回給代理和代理的調用者。

  

  圖1:正在進行的POJO編程

  您在POJO之外構建程序並對其進行配置,而餘下的工作就交給Spring。我是一名POJO程序員。

  3.依賴注入有助於可測試性

  通過一種稱爲依賴注入(Dependency Injection,DI)的設計模式,Spring極大地提高了可測試性。當客戶依賴於某種依賴性(我們將稱之爲一個服務)時,您將創建客戶的一個屬性。Spring將創建客戶和服務,然後把客戶的屬性設置爲服務的值。換言之,Spring負責管理上下文中bean的生命週期,並解決依賴性。下面給出一個依賴注入的例子,沒有使用Spring。我們首先來看客戶(應用程序的基本元素):

  public class CommandLineView {private RentABike rentaBike;public CommandLineView( ) {rentaBike = new ArrayListRentABike("Bruce's Bikes"); }public void setRentABike(RentABike rentABike){this.rentABike = rentABike;}public void printAllBikes( ) {System.out.println(rentaBike.toString( ));Iterator iter = rentaBike.getBikes().iterator( );while(iter.hasNext( )) {Bike bike = (Bike)iter.next( );System.out.println(bike.toString( ));}}public static final void main(String[] args) {CommandLineView clv = new CommandLineView( );clv.printAllBikes( );}}

  接下來是服務,即模型。它是一種帶有數組表的簡單實現。它對模型(RentaBike)具有依賴性。

  interface RentABike {List getBikes( );Bike getBike(String serialNo);}public class ArrayListRentABike implements RentABike {private String storeName;final List bikes = new ArrayList();public ArrayListRentABike(String storeName) {this.storeName = storeName;bikes.add(new Bike("Shimano", "Roadmaster", 20, "11111", 15, "Fair"));bikes.add(new Bike("Cannondale", "F2000 XTR", 18, "22222",12,"Excellent"));bikes.add(new Bike("Trek","6000", 19, "33333", 12.4, "Fair"));}public String toString() { return "RentABike: " + storeName; }public List getBikes() { return bikes; }public Bike getBike(String serialNo) {Iterator iter = bikes.iterator();while(iter.hasNext()) {Bike bike = (Bike)iter.next();if(serialNo.equals(bike.getSerialNo())) return bike;}return null;}}

  下面是一個彙編程序。以粗體表示的代碼就是依賴注入。彙編程序實例化了服務和客戶,然後通過設置rentaBike屬性來解決依賴性。

  public class RentABikeAssembler {public static final void main(String[] args) {CommandLineView clv = new CommandLineView( );RentABike rentaBike = new ArrayListRentABike("Bruce's Bikes");clv.setRentaBike(rentaBike);clv.printAllBikes( );}}

  當然,Spring最終將擔任彙編程序的角色。如果把服務包裝在一個接口中,就能夠把任何接口實現注入容器中。

 依賴注入使您可以編碼生產依賴性和測試依賴性。例如,本例創建了一個存根對象,從而可以更輕鬆地測試視圖。

  您已經看到了RentaBike的Hibernate實現和數組表版本。我不想在完整的Hibernate實現上運行所有的用戶接口測試。相反,我使用數組表簡單地實現了接口。

  依賴注入使您可以獲得一個生產版本(使用HibRentaBike)、一個開發版本(使用一個ArrayListRentaBike列表)和一個測試版本(使用一個mock對象)。使用Java編程時,我使用依賴注入把這些mock放到難於到達的地方中。

  4. 反向控制簡化了JDBC

  JDBC應用程序麻煩、冗長且乏味。一個好的抽象層會有很大幫助。Spring允許您使用查詢定製一個默認的JDBC方法和匿名內部類,以便減少大量的繁重工作。下面給出了一個簡單的JDBC例子:

  JdbcTemplate template = new JdbcTemplate(dataSource); final List names = new LinkedList();template.query("SELECT USER.NAME FROM USER", new RowCallbackHandler() { public void processRow(ResultSet rs) throws SQLException {names.add(rs.getString(1));}});

  把template.query方法當作一個默認的JDBC方法。Spring將爲結果集中的每一行執行匿名內部類中的processRow方法。您在上下文中配置數據源。您不必擔心打開或關閉語句或連接、配置數據源或管理事務等諸項事宜。您不用指定外部的結果集或者在最底層管理異常,因爲Spring把SQLException放到了一個未檢查異常的常見集合中。其他語言,比如Ruby和Smalltalk,通常使用包含代碼塊的反向控制,但是這在Java中並不十分常見。反向控制可以實現驚人的效果。

  5.Spring在社區中的繁榮

  一些開源項目不需要特別有用。例如,JUnit完成了預定的任務,如果您喜歡編程模型,它基本上擁有您所需要的一切功能。像Spring這樣的輕量級容器需要一個有活力的社區。Spring擁有您所能找到的最積極的社區之一,這對您有很多好處:

  ◆服務:藉助於Spring,您可以找到數以百計的不同服務,從安全性到系統管理,再到工作流。對於持久性,您可以插入JDO、Hibernate、Top Link、JDBC或OJB。

  ◆支持與培訓:許多獨立顧問都提供Spring服務,您可以在全球範圍內獲得優質的培訓。

  ◆增強:Spring一年推出好幾個版本。每個版本的質量都很不錯,框架中的測試性良好,擴展組成清晰。Spring已經開始支持Hibernate 3,並會提供一個功能強大的新Web流框架,這些都包括在最新的版本中。

  ◆商業支持:有很多人像我一樣編寫有關Spring的書籍。迄今爲止,可以找到5本專門講述Spring的書籍,還有一些書籍包含了Spring方面的內容。有幾家產品供應商也支持Spring。很多開源框架,比如Geronimo和Hibernate,對Spring提供特殊的支持。

  Spring社區使得使用這個框架變得更加容易。我可以僱傭Spring開發人員,對他們進行培訓。我可以閱讀書籍來補充我的知識,並針對需要做的工作獲取組件。我找不到另一個擁有其他類似的輕量級容器的社區。

發佈了20 篇原創文章 · 獲贊 10 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章