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

JAVA設計模式之事務處理[2]

2013-11-23 19:58:43  來源: Java高級技術 

import javalangreflectInvocationHandler;
import javalangreflectMethod;
import javalangreflectProxy;

import javasqlConnection;

import comstrutsletdemoserviceSystemException;

public final class TransactionWrapper {

    /**
     * 裝飾原始的業務代表對象返回一個與業務代表對象有相同接口的代理對象
     */
    public static Object decorate(Object delegate) {
        return ProxynewProxyInstance(delegategetClass()getClassLoader()
                delegategetClass()getInterfaces() new XAWrapperHandler(
                        delegate));
    }
   
    //動態代理技術
    static final class XAWrapperHandler implements InvocationHandler {
        private final Object delegate;

        XAWrapperHandler(Object delegate) {
           thisdelegate = delegate;
        }
       
        //簡單起見包裝業務代表對象所有的業務方法
        public Object invoke(Object proxy Method method Object[] args)
                throws Throwable {
            Object result = null;
            Connection con = ConnectionManagergetConnection();
            try {
                //開始一個事務
                consetAutoCommit(false);
                //調用原始業務對象的業務方法
                result = methodinvoke(delegate args);
                concommit();   //提交事務
                consetAutoCommit(true);
            } catch (Throwable t) {
                //回滾
                conrollback();
                consetAutoCommit(true);
                throw new SystemException(t);
            }

            return result;
        }
    }
}


    正如我們所見此對象只不過把業務對象需要事務控制的業務方法中的事務控制部分抽取出來而已請注意業務代表對象內部調用自身的方法將不會開始新的事務因為這些調用不會傳給代理對象如此我們去除了代表重復的味道此時我們的業務代表對象修改成


public class BookStoreManagerImpl implements BookStoreManager {
    public boolean buyBook(String bookId)throws SystemException{
          Connection conn=ConnectionManagergetConnection();// 獲取數據庫連接
          boolean b=false;
          try{
              BookDAO bookDAO=DAOFactorygetBookDAO();
              CustomerDAO customerDAO=DAOFactorygetCustomerDAO();
              // 嘗試從庫存中取書
              if(BookDAOreduceInventory(connbookIdquantity)){
                  BigDecimal price=BookDAOgetPrice(bookId);  // 取價格
                  // 從客戶帳戶中扣除price*quantity的費用
                  b=
                  CustomerDAOreduceAccount(connpricemultiply(new BigDecimal(quantity));
                 
                  其他業務方法如通知管理員生成定單等
                 
              }
          }catch(SQLException e){
             throws new SystemException(e);
          }
          return b;
    }
   
}

    可以看到此時的業務代表對象專注於實現業務邏輯它不再關心事務控制細節把它們全部委托給了外部對象業務代表工廠也修改一下讓它返回兩種類型的業務代表對象

 

public final class ManagerFactory {
      //返回一個被包裝的對象有事務控制能力
      public static BookStoreManager getBookStoreManagerTrans() {
          return (BookStoreManager) TransactionWrapper
                  decorate(new BookStoreManagerImpl());
      }
      //原始版本
      public static BookStoreManager getBookStoreManager() {
         return new BookStoreManagerImpl();
      }
     
   }

    我們在業務代表工廠上提供了兩種不同的對象生成方法一個用於創建被包裝的對象它會為每次方法調用創建一個新的事務另外一個用於創建未被包裝的版本它用於加入到已有的事務(比如其他業務代表對象的業務方法)解決了嵌套業務代表對象的問題
   我們的設計還不夠優雅比如我們默認所有的業務代表對象的方法調用都將被包裝在一個Transaction Context可事實是很多方法也許並不需要與數據庫打交道如果我們能配置哪些方法需要事務聲明哪些不需要事務管理就更完美了解決辦法也很簡單一個XML配置文件來配置這些調用時判斷即可說到這裡了解spring的大概都會意識到這不正是聲明式事務控制嗎?正是如此事務控制就是AOP的一種服務spring的聲明式事務管理是通過AOP實現的AOP的實現方式包括動態代理技術字節碼生成技術(如CGLIB庫)java代碼生成(早期EJB采用)修改類裝載器以及源代碼級別的代碼混合織入(aspectj)等我們這裡就是利用了動態代理技術只能對接口代理對類的動態代理可以使用cglib庫
    這篇短文只是介紹下我對事務上下文模式以及聲明式事務管理實現基本原理的理解如有錯誤請不吝賜教謝謝我的email:killme@gmailcom

 

[]  []  


From:http://tw.wingwit.com/Article/program/Java/gj/201311/27764.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.