這篇文章主要探討怎麼用Spring來裝配組件及其事務管理
在J
EE工程裡連接到一個簡單的數據庫並不是什麼難題
但是如果要綜合組裝企業類的組件就變得復雜了
一個簡單的組件有一個或多個數據庫支撐
所以
我們說到整合兩個或多個的組件時
我們希望能夠維持跨組件的許多數據庫的運作的原子性
J
EE提供了這些組件的容器
可以保證處理的原子性和獨立性
在沒有J
EE的情況下我們可以用Spring
Spring基於IoC模式(即反轉模式)
不僅可以配置組件服務
還可以配置相應的方法
為了更好的實現本文的目的
我們使用Hibernate來做相應的後台開發
裝配組件事務 假設在組件庫裡
我們已經有一個審核組件(audit component)
裡面有可以被客戶端調用的方法
接著
當我們想要構建一個處理訂單的體系
我們發現設計需要的OrderListManager組件服務同樣需要審核組件服務
OrderListManager創建和管理訂單
每一個服務都含有自己的事務屬性
當這時調用審核組件
就可以把OrderListManager的處理內容傳給它
也許將來新的業務服務(business service)同樣需要審核組件
那這時它調用的事務內容已經不一樣了
在網絡上的結果就是
雖然審核的功能保持不變
但是可以和別的事件功能組合在一起
用這些方法屬性來提供不同的運行時的處理參數
在圖
中有兩個分開的調用流程
在流程
裡
如果客戶端含有一個TX內容
OrderListManager 要由一個新的TX開始或者參與其中
取決於客戶端在不在TX裡以及OrderListManager方法指定的TX屬性
這在它調用AuditManager方法的時候仍然適用
圖 裝配組件事務 EJB體系通過裝配者聲明正確的事務屬性來獲得這種適應性
我們不是在探討是否聲明事務管理
因為這會使運行時的事務參數代碼發生改變
幾乎所有的J
EE工程提供了分布的事務管理來配合提交協議例如X/Open XA specification
現在的問題是我們能不能不用EJB來獲得相同的功能?Spring是其中一種解決方案
來看一下Spring如何處理這樣的問題
用Spring來管理事務 我們將看到的是一個輕量級的事務機制
實際上
它可以管理組件層的事務集成
Spring就是如此
它的優點是我們可以不用捆綁在J
EE的服務例如JNDI數據庫
最棒的是如果我們想把這個事務機制與已經存在的J
EE框架組合在一起
沒有任何問題
就好像我們找到了槓桿中完美的支撐點一樣
Spring的另一個機制是使用了AOP框架
這個框架使用了一個可以使用AOP的Spring bean factory
在Spring特定的配置文件applicationContext
xml裡通過特定的組件層的事件來指定
<beans><!
other code goes here
>
<bean id=
orderListManager
class=
org
springframework
transaction
interceptor
TransactionProxyFactoryBean
><property name=
transactionManager
>
<ref local=
transactionManager
/></property><property name=
target
>
<ref local=
orderListManagerTarget
/></property><property name=
transactionAttributes
>
<props><prop key=
getAllOrderList
> PROPAGATION_REQUIRED </prop>
<prop key=
getOrderList
> PROPAGATION_REQUIRED </prop> <prop key=
createOrderList
> PROPAGATION_REQUIRED </prop>
<prop key=
addLineItem
> PROPAGATION_REQUIRED
com
example
exception
FacadeException </prop> <prop key=
getAllLineItems
> PROPAGATION_REQUIRED
readOnly </prop>
<prop key=
queryNumberOfLineItems
> PROPAGATION_REQUIRED
readOnly </prop>
</props></property></bean></beans>
一旦我們在服務層指定了事務屬性
它們就被一個繼承org
springframework
transaction
PlatformTransactionManager 接口的類截獲
這個接口如下:
public interface PlatformTransactionManager{ TransactionStatus getTransaction (TransactionDefinition definition);
void commit(TransactionStatus status);
void rollback(TransactionStatus status);}
Hibernate事務管理 一旦我們決定了使用Hibernate作為ORM工具
我們下一步要做的就是用Hibernate特定的事務管理實例來配置
<beans><!
other code goes here
><bean id=
transactionManager
class=
org
springframework
orm
hibernate
HibernateTransactionManager
>
<property name=
sessionFactory
>
<ref local=
sessionFactory
/>
</property></bean></beans>
我們來看看什麼是
裝配組件事務
你也許注意到了那個OrderListManager 特有的TX屬性
那個服務層的組件
我們的工程的主要的東西在表
的BDOM裡:
educitycn/img_///gif > 圖 業務領域對象模型 (BDOM) 為了用實例說明
我們來列出工程裡的非功能需求(NFR)
事務在數據庫appfuse
裡保存
審核時要登入到另一個數據庫appfuse
裡
出於安全的考慮
數據庫有防火牆保護
事務組件可以重用
所有訪問事件必須經過在事務服務層的審核
出於以上的考慮
我們決定了OrderListManager 服務將委托任何審核記錄來調用已有的AuditManager 組件
這產生了表
這樣更細致的結構
educitycn/img_///gif > 圖 組件服務結構設計 值得注意的是
由於我們的NFR
我們要映射OrderListManager相關的事物到appfuse
數據庫裡去
而審核相關的到appfuse
這樣
任何審核的時候 OrderListManager 組件都會調用AuditManager 組件
我們認為OrderListManager 組件裡的所有方法都要執行
因為我們通過服務來創建次序和具體項目
那麼AuditManager 組件裡的服務呢? 因為它做的是審核的動作
我們關心的是為系統裡所有的事務記錄審核情況
這樣的需求是
即使事務事件失敗了
我們也要記錄登錄的審核情況
AuditManager 組件同樣要有自己的事件
因為它同樣與自己的數據庫有關聯
如下所示
<beans><!—其他代碼在這裡
><bean id=
auditManager
class=
org
springframework
transaction
interceptor
TransactionProxyFactoryBean
> <property name=
transactionManager
> <ref local=
transactionManager
/> </property>
<property name=
target
> <ref local=
auditManagerTarget
/> </property>
<property name=
transactionAttributes
>
<props>
<prop key=
log
>
PROPAGATION_REQUIRES_NEW
</prop>
</props>
</property></bean></beans>
我們現在把注意力放到這兩個事務createOrderList 和 addLineItem中來
作為我們的試驗
同時注意我們並沒有要求最好的設計——你可能注意到了 addLineItem 方法拋出了 FacadeException
而 createOrderList 沒有
在產品設計中
你也許希望每一個方法都處理異常
public class OrderListManagerImpl
implements OrderListManager{private AuditManager auditManager;public Long createOrderList (OrderList orderList){
Long orderId = orderListDAO
createOrderList(orderList);
auditManager
log(new AuditObject
(ORDER + orderId
CREATE));
return orderId;}public void addLineItem (Long orderId
LineItem lineItem)
throws FacadeException{
Long lineItemId = orderListDAO
addLineItem(orderId
lineItem);
auditManager
log(new AuditObject
(LINE_ITEM + lineItemId
CREATE));
int numberOfLineItems = orderListDAO
queryNumberOfLineItems(orderId);
if(numberOfLineItems >
){
log(
Added LineItem
+ lineItemId +
to Order
+ orderId +
;
But rolling back *** !
);
throw new FacadeException(
Make a new
Order for this line item
);
}
else{
log(
Added LineItem
+ lineItemId +
to Order
+ orderId +
);
}}//其他代碼在這裡}
要創建一個這個試驗的異常
我們已經介紹了其他事務規則規定一個特定的次序不能在同一行裡包含兩個項目
我們應該注意到createOrderList 和 addLineItem調用了auditManager
log() 方法
你應該也注意到了上面方法中的事務屬性
<bean id=
orderListManager
class=
org
springframework
transaction
interceptor
TransactionProxyFactoryBean
>
<pro
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28501.html