基於 struts+spring+ibatis 的輕量級 J2EE 開發

JpetStore 4.0 是 ibatis 的最新示例程序,基於 Struts MVC 框架(注:非傳統 Struts 開發模式),以 ibatis 作爲持久化層。該示例程序設計優雅,層次清晰,可以學習以及作爲一個高效率的編程模型參考。本文是在其基礎上,採用 Spring 對其中間層(業務層)進行改造。使開發量進一步減少,同時又擁有了 Spring 的一些好處…

1. 前言

JpetStore 4.0 是 ibatis 的最新示例程序。ibatis 是開源的持久層產品,包含 SQL Maps 2.0 和 Data Access Objects 2.0 框架。JpetStore 示例程序很好的展示瞭如何利用 ibatis 來開發一個典型的 J2EE web 應用程序。JpetStore 有如下特點:

  • ibatis 數據層
  • POJO 業務層
  • POJO 領域類
  • Struts MVC
  • JSP 表示層

以下是本文用到的關鍵技術介紹,本文假設您已經對 Struts,SpringFramewok,ibatis 有一定的瞭解,如果不是,請首先查閱附錄中的參考資料。

  • Struts 是目前 Java Web MVC 框架中不爭的王者。經過長達五年的發展,Struts 已經逐漸成長爲一個穩定、成熟的框架,並且佔有了 MVC 框架中最大的市場份額。但是 Struts 某些技術特性上已經落後於新興的 MVC 框架。面對 Spring MVC、Webwork2 這些設計更精密,擴展性更強的框架,Struts 受到了前所未有的挑戰。但站在產品開發的角度而言,Struts 仍然是最穩妥的選擇。本文的原型例子 JpetStore 4.0 就是基於 Struts 開發的,但是不拘泥於 Struts 的傳統固定用法,例如只用了一個自定義 Action 類,並且在 form bean 類的定義上也是開創性的,令人耳目一新,稍後將具體剖析一下。
  • Spring Framework 實際上是 Expert One-on-One J2EE Design and Development 一書中所闡述的設計思想的具體實現。Spring Framework 的功能非常多。包含 AOP、ORM、DAO、Context、Web、MVC 等幾個部分組成。Web、MVC 暫不用考慮,JpetStore 4.0 用的是更成熟的 Struts 和 JSP;DAO 由於目前 Hibernate、JDO、ibatis 的流行,也不考慮,JpetStore 4.0 用的就是 ibatis。因此最需要用的是 AOP、ORM、Context。Context 中,最重要的是 Beanfactory,它能將接口與實現分開,非常強大。目前 AOP 應用最成熟的還是在事務管理上。
  • ibatis 是一個功能強大實用的 SQL Map 工具,不同於其他 ORM 工具(如 hibernate),它是將 SQL 語句映射成 Java 對象,而對於 ORM 工具,它的 SQL 語句是根據映射定義生成的。ibatis 以 SQL 開發的工作量和數據庫移植性上的讓步,爲系統設計提供了更大的自由空間。有 ibatis 代碼生成的工具,可以根據 DDL 自動生成 ibatis 代碼,能減少很多工作量。

2. JpetStore 簡述

2.1. 背景

最初是 Sun 公司的 J2EE petstore,其最主要目的是用於學習 J2EE,但是其缺點也很明顯,就是過度設計了。接着 Oracle 用 J2EE petstore 來比較各應用服務器的性能。微軟推出了基於 .Net 平臺的 Pet shop,用於競爭 J2EE petstore。而 JpetStore 則是經過改良的基於 struts 的輕便框架 J2EE web 應用程序,相比來說,JpetStore 設計和架構更優良,各層定義清晰,使用了很多最佳實踐和模式,避免了很多"反模式",如使用存儲過程,在 java 代碼中嵌入 SQL 語句,把 HTML 存儲在數據庫中等等。最新版本是 JpetStore 4.0。

2.2. JpetStore 開發運行環境的建立

1、開發環境

  • Java SDK 1.4.2
  • Apache Tomcat 4.1.31
  • Eclipse-SDK-3.0.1-win32
  • HSQLDB 1.7.2

2、Eclipse 插件

  • EMF SDK 2.0.1:Eclipse 建模框架,lomboz 插件需要,可以使用 runtime 版本。
  • lomboz 3.0:J2EE 插件,用來在 Eclipse 中開發 J2EE 應用程序
  • Spring IDE 1.0.3:Spring Bean 配置管理插件
  • xmlbuddy_2.0.10:編輯 XML,用免費版功能即可
  • tomcatPluginV3:tomcat 管理插件
  • Properties Editor:編輯 java 的屬性文件 , 並可以預覽以及自動存盤爲 Unicode 格式。免去了手工或者 ANT 調用 native2ascii 的麻煩。

3、示例源程序

  • ibatis 示例程序 JpetStore 4.0 http://www.ibatis.com/jpetstore/jpetstore.html
  • 改造後的源程序(+spring)(源碼鏈接)

2.3. 架構


圖 1 JpetStore 架構圖
圖 1 JpetStore 架構圖

圖 1 是 JPetStore 架構圖,更詳細的內容請參見 JPetStore 的白皮書。參照這個架構圖,讓我們稍微剖析一下源代碼,得出 JpetStore 4.0 的具體實現圖(見圖 2),思路一下子就豁然開朗了。前言中提到的非傳統的 struts 開發模式,關鍵就在 struts Action 類和 form bean 類上。

struts Action 類只有一個:BeanAction。沒錯,確實是一個!與傳統的 struts 編程方式很不同。再仔細研究 BeanAction 類,發現它其實是一個通用類,利用反射原理,根據 URL 來決定調用 formbean 的哪個方法。BeanAction 大大簡化了 struts 的編程模式,降低了對 struts 的依賴(與 struts 以及 WEB 容器有關的幾個類都放在 com.ibatis.struts 包下,其它的類都可以直接複用)。利用這種模式,我們會很容易的把它移植到新的框架如 JSF,spring。

這樣重心就轉移到 form bean 上了,它已經不是普通意義上的 form bean 了。查看源代碼,可以看到它不僅僅有數據和校驗 / 重置方法,而且已經具有了行爲,從這個意義上來說,它更像一個 BO(Business Object)。這就是前文講到的,BeanAction 類利用反射原理,根據 URL 來決定調用 form bean 的哪個方法(行爲)。form bean 的這些方法的簽名很簡單,例如:


 public String myActionMethod() { 
   //..work 
   return "success"; 
 } 

方法的返回值直接就是字符串,對應的是 forward 的名稱,而不再是 ActionForward 對象,創建 ActionForward 對象的任務已經由 BeanAction 類代勞了。

另外,程序還提供了 ActionContext 工具類,該工具類封裝了 request 、response、form parameters、request attributes、session attributes 和 application attributes 中的數據存取操作,簡單而線程安全,form bean 類使用該工具類可以進一步從表現層框架解耦。

在這裏需要特別指出的是,BeanAction 類是對 struts 擴展的一個有益嘗試,雖然提供了非常好的應用開發模式,但是它還非常新,一直在發展中。


圖 2 JpetStore 4.0 具體實現
圖 2 JpetStore 4.0 具體實現

2.4. 代碼剖析

下面就讓我們開始進一步分析 JpetStore4.0 的源代碼,爲下面的改造鋪路。

  • BeanAction.java 是唯一一個 Struts action 類,位於 com.ibatis.struts 包下。正如上文所言,它是一個通用的控制類,利用反射機制,把控制轉移到 form bean 的某個方法來處理。詳細處理過程參考其源代碼,簡單明晰。
  • Form bean 類位於 com.ibatis.jpetstore.presentation 包下,命名規則爲 ***Bean。Form bean 類全部繼承於 BaseBean 類,而 BaseBean 類實際繼承於 ActionForm,因此,Form bean 類就是 Struts 的 ActionForm,Form bean 類的屬性數據就由 struts 框架自動填充。而實際上,JpetStore4.0 擴展了 struts 中 ActionForm 的應用: Form bean 類還具有行爲,更像一個 BO, 其行爲(方法)由 BeanAction 根據配置(struts-config.xml)的 URL 來調用。雖然如此,我們還是把 Form bean 類定位於表現層。

    Struts-config.xml 的配置裏有 3 種映射方式,來告訴 BeanAction 把控制轉到哪個 form bean 對象的哪個方法來處理。

    以這個請求連接爲例 http://localhost/jpetstore4/shop/viewOrder.do

    1. URL Pattern

        <action path="/shop/viewOrder" type="com.ibatis.struts.BeanAction"
        name="orderBean" scope="session"
        validate="false"> 
        <forward name="success" path="/order/ViewOrder.jsp"/> 
      </action> 
     

    此種方式表示,控制將被轉發到"orderBean"這個 form bean 對象 的"viewOrder"方法(行爲)來處理。方法名取"path"參數的以"/"分隔的最後一部分。

    2. Method Parameter

        <action path="/shop/viewOrder" type="com.ibatis.struts.BeanAction"
        name="orderBean" parameter="viewOrder" scope="session"
        validate="false"> 
        <forward name="success" path="/order/ViewOrder.jsp"/> 
      </action> 
     

    此種方式表示,控制將被轉發到"orderBean"這個 form bean 對象的"viewOrder"方法(行爲)來處理。配置中的"parameter"參數表示 form bean 類上的方法。"parameter"參數優先於"path"參數。

    3. No Method call

        <action path="/shop/viewOrder" type="com.ibatis.struts.BeanAction"
        name="orderBean" parameter="*" scope="session"
        validate="false"> 
        <forward name="success" path="/order/ViewOrder.jsp"/> 
      </action> 
     

    此種方式表示,form bean 上沒有任何方法被調用。如果存在"name"屬性,則 struts 把表單參數等數據填充到 form bean 對象後,把控制轉發到"success"。否則,如果 name 爲空,則直接轉發控制到"success"。

    這就相當於 struts 內置的 org.apache.struts.actions.ForwardAction 的功能

     <action path="/shop/viewOrder" type="org.apache.struts.actions.ForwardAction"
        parameter="/order/ViewOrder.jsp " scope="session" validate="false"> 
     </action> 
    

  • Service 類位於 com.ibatis.jpetstore.service 包下,屬於業務層。這些類封裝了業務以及相應的事務控制。Service 類由 form bean 類來調用。
  • com.ibatis.jpetstore.persistence.iface 包下的類是 DAO 接口,屬於業務層,其屏蔽了底層的數據庫操作,供具體的 Service 類來調用。DaoConfig 類是工具類(DAO 工廠類),Service 類通過 DaoConfig 類來獲得相應的 DAO 接口,而不用關心底層的具體數據庫操作,實現瞭如圖 2 中 { 耦合 2} 的解耦。
  • com.ibatis.jpetstore.persistence.sqlmapdao 包下的類是對應 DAO 接口的具體實現,在 JpetStore4.0 中採用了 ibatis 來實現 ORM。這些實現類繼承 BaseSqlMapDao 類,而 BaseSqlMapDao 類則繼承 ibatis DAO 框架中的 SqlMapDaoTemplate 類。ibatis 的配置文件存放在 com.ibatis.jpetstore.persistence.sqlmapdao.sql 目錄下。這些類和配置文件位於數據層
  • Domain 類位於 com.ibatis.jpetstore.domain 包下,是普通的 javabean。在這裏用作數據傳輸對象(DTO),貫穿視圖層、業務層和數據層,用於在不同層之間傳輸數據。

剩下的部分就比較簡單了,請看具體的源代碼,非常清晰。

2.5. 需要改造的地方

JpetStore4.0 的關鍵就在 struts Action 類和 form bean 類上,這也是其精華之一(雖然該實現方式是試驗性,待擴充和驗證),在此次改造中我們要保留下來,即控制層一點不變,表現層獲取相應業務類的方式變了(要加載 spring 環境),其它保持不變。要特別關注的改動是業務層和持久層,幸運的是 JpetStore4.0 設計非常好,需要改動的地方非常少,而且由模式可循,如下:

1. 業務層和數據層用 Spring BeanFactory 機制管理。

2. 業務層的事務由 spring 的 aop 通過聲明來完成。

3. 表現層(form bean)獲取業務類的方法改由自定義工廠類來實現(加載 spring 環境)。


3. JPetStore 的改造

3.1. 改造後的架構



其中紅色部分是要增加的部分,藍色部分是要修改的部分。下面就讓我們逐一剖析。

3.2. Spring Context 的加載

爲了在 Struts 中加載 Spring Context,一般會在 struts-config.xml 的最後添加如下部分:


 <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> 
 <set-property property="contextConfigLocation"
 value="/WEB-INF/applicationContext.xml" /> 
 </plug-in> 

Spring 在設計時就充分考慮到了與 Struts 的協同工作,通過內置的 Struts Plug-in 在兩者之間提供了良好的結合點。但是,因爲在這裏我們一點也不改動 JPetStore 的控制層 ( 這是 JpetStore4.0 的精華之一 ),所以本文不準備採用此方式來加載 ApplicationContext。我們利用的是 spring framework 的 BeanFactory 機制 , 採用自定義的工具類(bean 工廠類)來加載 spring 的配置文件,從中可以看出 Spring 有多靈活,它提供了各種不同的方式來使用其不同的部分 / 層次,您只需要用你想用的,不需要的部分可以不用。

具體的來說,就是在 com.ibatis.spring 包下創建 CustomBeanFactory 類,spring 的配置文件 applicationContext.xml 也放在這個目錄下。以下就是該類的全部代碼,很簡單:


public final class CustomBeanFactory { 
    static XmlBeanFactory factory = null; 
    static { 
        Resource is = new InputStreamResource( 
            CustomBeanFactory.class.getResourceAsStream("applicationContext.xml"));
        factory = new XmlBeanFactory(is);             
    } 
    public static Object getBean(String beanName){ 
        return factory.getBean(beanName); 
    } 
} 

實際上就是封裝了 Spring 的 XMLBeanFactory 而已,並且 Spring 的配置文件只需要加載一次,以後就可以直接用 CustomBeanFactory.getBean("someBean") 來獲得需要的對象了 ( 例如 someBean),而不需要知道具體的類。CustomBeanFactory 類用於 { 耦合 1} 的解耦。

CustomBeanFactory 類在本文中只用於表現層的 form bean 對象獲得 service 類的對象,因爲我們沒有把 form bean 對象配置在 applicationContext.xml 中。但是,爲什麼不把表現層的 form bean 類也配置起來呢,這樣就用不着這 CustomBeanFactory 個類了,Spring 會幫助我們創建需要的一切?問題的答案就在於 form bean 類是 struts 的 ActionForm 類!如果大家熟悉 struts,就會知道 ActionForm 類是 struts 自動創建的:在一次請求中,struts 判斷,如果 ActionForm 實例不存在,就創建一個 ActionForm 對象,把客戶提交的表單數據保存到 ActionForm 對象中。因此 formbean 類的對象就不能由 spring 來創建,但是 service 類以及數據層的 DAO 類可以,所以只有他們在 spring 中配置。

所以,很自然的,我們就創建了 CustomBeanFactory 類,在表現層來銜接 struts 和 spring。就這麼簡單,實現了另一種方式的 { 耦合一 } 的解耦。

3.3. 表現層

上面分析到,struts 和 spring 是在表現層銜接起來的,那麼表現層就要做稍微的更改,即所需要的 service 類的對象創建上。以表現層的 AccountBean 類爲例:

原來的源代碼如下


    private static final AccountService accountService = AccountService.getInstance(); 
  private static final CatalogService catalogService = CatalogService.getInstance(); 
 

改造後的源代碼如下


private static final AccountService accountService = 
    (AccountService)CustomBeanFactory.getBean("AccountService"); 
private static final CatalogService catalogService = 
    (CatalogService)CustomBeanFactory.getBean("CatalogService"); 

其他的幾個 presentation 類以同樣方式改造。這樣,表現層就完成了。關於表現層的其它部分如 JSP 等一概不動。也許您會說,沒有看出什麼特別之處的好處啊?你還是額外實現了一個工廠類。彆着急,帷幕剛剛開啓,spring 是在表現層引入,但您發沒發現:

  • presentation 類僅僅面向 service 類的接口編程,具體"AccountService"是哪個實現類,presentation 類不知道,是在 spring 的配置文件裏配置。(本例中,爲了最大限度的保持原來的代碼不作變化,沒有抽象出接口)。Spring 鼓勵面向接口編程,因爲是如此的方便和自然,當然您也可以不這麼做。
  • CustomBeanFactory 這個工廠類爲什麼會如此簡單,因爲其直接使用了 Spring 的 BeanFactory。Spring 從其核心而言,是一個 DI 容器,其設計哲學是提供一種無侵入式的高擴展性的框架。爲了實現這個目標,Spring 大量引入了 Java 的 Reflection 機制,通過動態調用的方式避免硬編碼方式的約束,並在此基礎上建立了其核心組件 BeanFactory,以此作爲其依賴注入機制的實現基礎。org.springframework.beans 包中包括了這些核心組件的實現類,核心中的核心爲 BeanWrapper 和 BeanFactory 類。

3.4. 持久層

在討論業務層之前,我們先看一下持久層,如下圖所示:



在上文中,我們把 iface 包下的 DAO 接口歸爲業務層,在這裏不需要做修改。ibatis 的 sql 配置文件也不需要改。要改的是 DAO 實現類,並在 spring 的配置文件中配置起來。

1、修改基類

所有的 DAO 實現類都繼承於 BaseSqlMapDao 類。修改 BaseSqlMapDao 類如下:


 public class BaseSqlMapDao extends SqlMapClientDaoSupport { 
  protected static final int PAGE_SIZE = 4; 
  protected SqlMapClientTemplate smcTemplate = this.getSqlMapClientTemplate(); 
  public BaseSqlMapDao() { 
	 } 
 } 

使 BaseSqlMapDao 類改爲繼承於 Spring 提供的 SqlMapClientDaoSupport 類,並定義了一個保護屬性 smcTemplate,其類型爲 SqlMapClientTemplate。關於 SqlMapClientTemplate 類的詳細說明請參照附錄中的"Spring 中文參考手冊"

2、修改 DAO 實現類

所有的 DAO 實現類還是繼承於 BaseSqlMapDao 類,實現相應的 DAO 接口,但其相應的 DAO 操作委託 SqlMapClientTemplate 來執行,以 AccountSqlMapDao 類爲例,部分代碼如下:


public List getUsernameList() { 
    return smcTemplate.queryForList("getUsernameList", null); 
} 

public Account getAccount(String username, String password) { 
    Account account = new Account(); 
    account.setUsername(username); 
    account.setPassword(password); 
    return (Account) smcTemplate
        .queryForObject("getAccountByUsernameAndPassword", account); 
} 
  
public void insertAccount(Account account) { 
    smcTemplate.update("insertAccount", account); 
    smcTemplate.update("insertProfile", account); 
    smcTemplate.update("insertSignon", account); 
} 
 

就這麼簡單,所有函數的簽名都是一樣的,只需要查找替換就可以了!

3、除去工廠類以及相應的配置文件

除去 DaoConfig.java 這個 DAO 工廠類和相應的配置文件 dao.xml,因爲 DAO 的獲取現在要用 spring 來管理。

4、DAO 在 Spring 中的配置(applicationContext.xml)


    <bean id="dataSource" 
        class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
        <property name="driverClassName"> 
            <value>org.hsqldb.jdbcDriver</value> 
        </property> 
        <property name="url"> 
            <value>jdbc:hsqldb:hsql://localhost/xdb</value> 
        </property> 
        <property name="username"> 
            <value>sa</value> 
        </property> 
        <property name="password"> 
            <value></value> 
        </property> 
    </bean>    
    <!-- ibatis sqlMapClient config --> 
    <bean id="sqlMapClient" 
        class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> 
        <property name="configLocation"> 
            <value> 
            classpath:com\ibatis\jpetstore\persistence\sqlmapdao\sql\sql-map-config.xml
            </value> 
        </property> 
        <property name="dataSource"> 
            <ref bean="dataSource"/> 
        </property>    
    </bean> 
    <!-- Transactions --> 
    <bean id="TransactionManager" 
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource"> 
            <ref bean="dataSource"/> 
        </property> 
    </bean> 
    <!-- persistence layer --> 
    <bean id="AccountDao" 
        class="com.ibatis.jpetstore.persistence.sqlmapdao.AccountSqlMapDao"> 
        <property name="sqlMapClient"> 
            <ref local="sqlMapClient"/> 
        </property> 
    </bean> 
   

具體的語法請參照附錄中的"Spring 中文參考手冊"。在這裏只簡單解釋一下:

1. 我們首先創建一個數據源 dataSource,在這裏配置的是 hsqldb 數據庫。如果是 ORACLE 數據庫,driverClassName 的值是"oracle.jdbc.driver.OracleDriver",URL 的值類似於"jdbc:oracle:thin:@wugfMobile:1521:cdcf"。數據源現在由 spring 來管理,那麼現在我們就可以去掉 properties 目錄下 database.properties 這個配置文件了;還有不要忘記修改 sql-map-config.xml,去掉 <properties resource="properties/database.properties"/> 對它的引用。

2. sqlMapClient 節點。這個是針對 ibatis SqlMap 的 SqlMapClientFactoryBean 配置。實際上配置了一個 sqlMapClient 的創建工廠類。configLocation 屬性配置了 ibatis 映射文件的名稱。dataSource 屬性指向了使用的數據源,這樣所有使用 sqlMapClient 的 DAO 都默認使用了該數據源,除非在 DAO 的配置中另外顯式指定。

3. TransactionManager 節點。定義了事務,使用的是 DataSourceTransactionManager。

4. 下面就可以定義 DAO 節點了,如 AccountDao,它的實現類是 com.ibatis.jpetstore.persistence.sqlmapdao.AccountSqlMapDao,使用的 SQL 配置從 sqlMapClient 中讀取,數據庫連接沒有特別列出,那麼就是默認使用 sqlMapClient 配置的數據源 datasource。

這樣,我們就把持久層改造完了,其他的 DAO 配置類似於 AccountDao。怎麼樣?簡單吧。這次有接口了:) AccountDao 接口->AccountSqlMapDao 實現。

3.5. 業務層

業務層的位置以及相關類,如下圖所示:



在這個例子中只有 3 個業務類,我們以 OrderService 類爲例來改造,這個類是最複雜的,其中涉及了事務。

1、在 ApplicationContext 配置文件中增加 bean 的配置:


    <bean id="OrderService" 
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> 
        <property name="transactionManager"> 
            <ref local="TransactionManager"></ref> 
        </property> 
        <property name="target"> 
            <bean class="com.ibatis.jpetstore.service.OrderService"> 
                <property name="itemDao"> 
                    <ref bean="ItemDao"/> 
                </property> 
                <property name="orderDao"> 
                    <ref bean="OrderDao"/> 
                </property> 
                <property name="sequenceDao"> 
                    <ref bean="SequenceDao"/> 
                </property> 
            </bean> 
        </property> 
        <property name="transactionAttributes"> 
            <props> 
                <prop key="insert*">PROPAGATION_REQUIRED</prop> 
            </props> 
        </property> 
    </bean> 
   

定義了一個 OrderService,還是很容易懂的。爲了簡單起見,使用了嵌套 bean,其實現類是 com.ibatis.jpetstore.service.OrderService,分別引用了 ItemDao,OrderDao,SequenceDao。該 bean 的 insert* 實現了事務管理 (AOP 方式 )。TransactionProxyFactoryBean 自動創建一個事務 advisor, 該 advisor 包括一個基於事務屬性的 pointcut, 因此只有事務性的方法被攔截。

2、業務類的修改

以 OrderService 爲例:


 public class OrderService { 
   /* Private Fields */ 
  private ItemDao itemDao; 
  private OrderDao orderDao; 
  private SequenceDao sequenceDao; 
  /* Constructors */ 
  public OrderService() { 
  } 
 /** 
 * @param itemDao 要設置的 itemDao。
 */ 
 public final void setItemDao(ItemDao itemDao) { 
	 this.itemDao = itemDao; 
 } 
 /** 
 * @param orderDao 要設置的 orderDao。
 */ 
 public final void setOrderDao(OrderDao orderDao) { 
	 this.orderDao = orderDao; 
 } 
 /** 
 * @param sequenceDao 要設置的 sequenceDao。
 */ 
 public final void setSequenceDao(SequenceDao sequenceDao) { 
	 this.sequenceDao = sequenceDao; 
 } 
 // 剩下的部分
…… . 
 } 

紅色部分爲修改部分。Spring 採用的是 Type2 的設置依賴注入,所以我們只需要定義屬性和相應的設值函數就可以了,ItemDao,OrderDao,SequenceDao 的值由 spring 在運行期間注入。構造函數就可以爲空了,另外也不需要自己編寫代碼處理事務了(事務在配置中聲明),daoManager.startTransaction(); 等與事務相關的語句也可以去掉了。和原來的代碼比較一下,是不是處理精簡了很多!可以更關注業務的實現。


4. 結束語

ibatis 是一個功能強大實用的 SQL Map 工具,可以直接控制 SQL, 爲系統設計提供了更大的自由空間。其提供的最新示例程序 JpetStore 4.0, 設計優雅,應用了迄今爲止很多最佳實踐和設計模式,非常適於學習以及在此基礎上創建輕量級的 J2EE WEB 應用程序。JpetStore 4.0 是基於 struts 的,本文在此基礎上,最大程度保持了原有設計的精華以及最小的代碼改動量,在業務層和持久化層引入了 Spring。在您閱讀了本文以及改造後的源代碼後,會深切的感受到 Spring 帶來的種種好處:自然的面向接口的編程,業務對象的依賴注入,一致的數據存取框架和聲明式的事務處理,統一的配置文件…更重要的是 Spring 既是全面的又是模塊化的,Spring 有分層的體系結構,這意味着您能選擇僅僅使用它任何一個獨立的部分,就像本文,而它的架構又是內部一致。


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