多數
IT
組織都必須解決三個主要問題:
1
.幫助組織減少成本
2
.增加并且保持客戶
3
.加快業務效率。完成這些問題一般都需要實現對多個業務系統的數據和業務邏輯的無縫訪問,也就是說,要實施系統集成工程,以便聯結業務流程、實現數據的訪問與共享。
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
建??蚣埽?/span>
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
架構圖,更詳細的內容請參見
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.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
有分層的體系結構,這意味著您能選擇僅僅使用它任何一個獨立的部分,就像本文,而它的架構又是內部一致。
參考資料
??????作者Blog:http://blog.csdn.net/yanwp/