熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

技術分享 在Spring中實現事務掛起(圖)

2022-06-13   來源: Java開源技術 

  摘要
  
  Spring Framework是一個流行的Java/JEE應用框架它構建於一個輕量級的反向控制(InversionofControlQoC)模式的容器的基礎之上以其數據訪問和事務管理能力而著稱Spring的聲明性事務劃分適用於任何的POJO(pure old java object或plain ordinary Java object無格式普通Java對象)目標對象其聲明性事務如同EJB容器托管事務(ContainerManaged TransactionCMT)一樣完善後端事務管理器的選擇包括簡單的基於JDBC的事務和完善的JEE事務(借助於JTA策略)
  
  本文詳細討論了Spring的事務管理功能重點介紹了如何以JTA作為後端事務策略使用Spring的針對POJO的聲明性事務本文說明了Spring的事務服務可以與JEE服務器的事務協調程序(如BEA WebLogic Server的事務協調程序)進行無縫交互實際上已經成為EJB CMT的傳統事務劃分方式的替代方案
  
  針對POJO的聲明性事務
  
  為了說明Spring的聲明性事務劃分方式讓我們來看看Spring的PetClinic示例應用程序的中央服務外觀(facade)的配置
  
  <bean id=dataSource
  class=orgspringframeworkjndiJndiObjectFactoryBean>
  <property name=jndiName>
  <value>java:comp/env/jdbc/petclinic</value>
  </property>
  </bean>
  <bean id=transactionManager
  class=orgspringframeworktransactionjtaJtaTransactionManager/>
  
  <bean id=clinicTarget
  class=orgspringframeworksamplespetclinicjdbcJdbcClinic>
  <property name=dataSource><ref bean=dataSource/></property>
  </bean>
  
  <bean id=clinic
  class=orgspringframeworktransactioninterceptorTransactionProxyFactoryBean>
  <property name=transactionManager><ref bean=transactionManager/></property>
  <property name=target><ref bean=clinicTarget/></property>
  <property name=transactionAttributes>
  <props>
  <prop key=load*>PROPAGATION_REQUIREDreadOnly</prop>
  <prop key=store*>PROPAGATION_REQUIRED</prop>
  </props>
  </property>
  </bean>
  
  它遵從了Spring的標准XMLBean定義格式它定義了
  
  一個DataSource引用指向一個JNDI位置這將從JEE服務器托管的JNDI環境中獲取指定的DataSource
  
  一個PlatformTransactionManage實現在本例中該實現指定Spring的JtaTransactionManager它委托給JEE服務器的事務協調程序
  
  應用程序服務實現這是一個簡單的POJO它封裝了業務和數據訪問邏輯它實現應用程序的Clinic服務接口
  
  一個應用程序服務的事務代理該代理定義了目標服務的事務屬性提供具體的方法命名模式並創建相應的事務對於實際的事務管理代理指向PlatformTransactionManager實現
  
  注意Spring還通過通用屬性(Commons Attribute)或者JSE 的注釋(annotation)支持一種自動代理機制和對源級(sourcelevel)元數據的使用作為顯示代理定義的替代方案這些替代方案不在本文的討論范圍之內其詳細資料請參考Spring說明文檔
  
  使用的服務接口和服務實現是特定於應用程序的無需了解Spring(具體說是Spring的事務管理)就可以實現純Java對象可以用作目標對象而任何一個純Java接口都可以用作服務接口下面是一個Clinic接口的例子
  
  public interface Clinic {
  Pet loadPet(int id);
  void storePet(Pet pet);
  
  }
  下面顯示了該接口的一個簡單實現假定它使用JDBC來執行必要的數據訪問它通過一個bean屬性的setter方法接收JDBC DataSource這直接對應上面配置中的dataSource屬性定義
  
  public class JdbcClinic implements Clinic {
  
  private DataSource dataSource;
  
  public void setDataSource(DataSource dataSource) {
  thisdataSource = dataSource;
  }
  
  public Pet loadPet(int id) {
  try {
  Connection con = thisdataSourcegetConnection();
  
  }
  catch (SQLException ex) {
  
  }
  }
  
  public void storePet(Pet pet) {
  try {
  Connection con = thisdataSourcegetConnection();
  
  }
  catch (SQLException ex) {
  
  }
  }
  
  
  }
  正如您所看到的代碼簡單明了使用了一個簡單Java對象事務管理由事務代理處理我們隨後再對其進行說明
  
  注意PetClinic示例應用程序中實際的基於JDBC的Clinic實現利用了Spring的JDBC支持類以免只工作在簡單的JDBC API級別上但是Spring的事務管理還將使用簡單的基於JDBC的實現比如上面的實現
  
  定義事務代理
  
  除JdbcClinic實例之外配置還為其定義了一個事務代理如果需要可以顯式地指定該事務代理所暴露的實際接口默認狀態下目標對象實現的所有接口都將被暴露在本例中是應用程序的Clinic服務接口
  
  從客戶端的角度來看clinicbean只是應用程序的Clinic接口的實現客戶端不必知道自己正在和事務代理打交道這就是接口的力量目標對象的直接引用可以很輕松地由實現了相同接口的代理取代在本例中是一個隱式地創建事務的代理
  
  對於特定的方法或方法命名模式代理的具體事務行為由事務屬性驅動如下面的例子所示
  
  <prop key=load*>PROPAGATION_REQUIREDreadOnly</prop><prop key=store*>PROPAGATION_REQUIRED</prop>
  
  key屬性確定代理應該給哪個方法增加事務行為這樣的屬性最重要的部份是傳播行為有以下選項可供使用
  
  PROPAGATION_REQUIRED支持當前事務如果當前沒有事務就新建一個事務這是最常見的選擇
  PROPAGATION_SUPPORTS支持當前事務如果當前沒有事務就以非事務方式執行
  PROPAGATION_MANDATORY支持當前事務如果當前沒有事務就拋出異常
  PROPAGATION_REQUIRES_NEW新建事務如果當前存在事務把當前事務掛起
  PROPAGATION_NOT_SUPPORTED以非事務方式執行操作如果當前存在事務就把當前事務掛起
  PROPAGATION_NEVER以非事務方式執行如果當前存在事務則拋出異常
  PROPAGATION_NESTED如果當前存在事務則在嵌套事務內執行如果當前沒有事務則進行與PROPAGATION_REQUIRED類似的操作
  
  前六個策略類似於EJB CMT常量名相同因此對EJB開發人員來說應該立刻就感到熟悉第七個(PROPAGATION_NESTED)是Spring所提供的一個特殊變量它要求事務管理器或者使用JDBC Savepoint API提供嵌套事務行為(如Spring的DataSourceTransactionManager)或者通過JTA支持嵌套事務
  
  事務屬性中的readOnly標志表示對應的事務應該被最優化為只讀事務這是一個最優化提示在一些情況下一些事務策略能夠起到顯著的最優化效果例如在使用Object/Relational映射工具(如Hibernate或TopLink)時避免dirty checking(試圖刷新
  
  在事務屬性中還有定義timeout值的選項指定事務超時為幾秒在JTA中這將被簡單地傳遞到JEE服務器的事務協調程序並據此得到相應的解釋
  
  使用事務代理
  
  在運行時客戶端將獲取到clinicbean的引用將其轉換為Clinic接口同時在它上面調用諸如loadPet或storePet之類的操作這將隱式地使用在目標對象之前注冊的事務攔截器檢查Spring的事務代理新的事務將被創建然後調用將被委派給JdbcClinic目標方法
  
  圖說明了一個具有advisor鏈和終端目標的AOP代理的底層概念其中唯一的advisor就是將事務行為包裝到目標方法的事務攔截器這是在Spring的聲明性事務功能的幫助下產生的基於代理的AOP(面向方面編程)
  
 educitycn/img_///jpg >
  圖 具有advisor鏈和終端目標的AOP代理

  
  例如PetClinic web應用程序中的web層組件能夠執行ServletContext查詢操作來獲取對Spring WebApplicationContext的引用然後獲得那裡托管的Clinicbean
  
  WebApplicationContext ctx =
  WebApplicationContexUtilsgetWebApplicationContext(servletContext);
  Clinic clinic = (Clinic) ctxgetBean(clinic);
  
  Pet pet = new Pet();
  petsetName(my new cat);
  
  clinicstorePet(pet);  在storePet()調用的開始Spring的事務代理將隱式地創建一個事務在storePet()調用返回時將提交或回滾事務默認情況下任何RuntimeException或Error的拋出均會導致回滾可以指定何時提交和何時回滾的實際規則Spring的事務屬性支持一個稱為回滾規則的概念
  
  例如我們可以引入一個檢查性的PetClinicException並告訴事務代理在拋出該異常時執行進行回滾
  
  <prop key=load*>PROPAGATION_REQUIREDreadOnlyPetClinicException</prop>
  <
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28657.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.