1. 程式人生 > >Spring對事務的支持

Spring對事務的支持

bsp ddt nag 支持 切點 requires comm 特定 eas

1、ThreadLocal

  在寫Spring對事務的支持之前要先了解一下ThreadLocal,當多個線程訪問同一個成員變量時,如果這個變量不做處理,那肯定會造成線程不安全的問題啊。使用ThreadLocal就可以解決這個問題,ThreadLocal為每一個線程創建變量的一個副本,這樣線程操作的其實是各自的副本,就不會產生線程不安全的問題。下面看個例子:

public class ThreadLocalTest {
    private ThreadLocal<Integer> num=new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue() {
            return 0;
        }
    };

    Integer getNextNum(){
        num.set(num.get()+1);
        return num.get();
    };

    public static void  main(String[] args){
        ThreadLocalTest th=new ThreadLocalTest();
        Test t1=new Test(th);
        Test t2=new Test(th);
        Test t3=new Test(th);
        t1.start();
        t2.start();
        t3.start();
    }
} 

  

public class Test  extends Thread{    private ThreadLocalTest th;    public Test(ThreadLocalTest th) {        this.th = th;    }    @Override    public void run() {        for (int i=0;i<3;i++){            System.out.println("thread["+Thread.currentThread().getName()+"] th["+th.getNextNum()+"]");        }    }}
//運行結果
thread[Thread-1] th[1]
thread[Thread-0] th[1]
thread[Thread-0] th[2]
thread[Thread-0] th[3]
thread[Thread-2] th[1]
thread[Thread-2] th[2]
thread[Thread-2] th[3]
thread[Thread-1] th[2]
thread[Thread-1] th[3]

  

運行結果顯示了,雖然三個線程同時訪問了一個對象,但是並沒有互相影響,成員變量都是從初始值開始的。

  ThreadLocal有四個方法:

  1、protectd T initiaValue():給變量設置初始值

  2、public T get():獲取當前線程當前變量的值

  3、public void set(T value):給當前線程的副本設值

  4、public void remove() :刪除當前線程的副本

2、Spring對事務管理的支持

  spring提供了三個接口對事務進行管理,然後提供了實現類對不同的持久層框架進行支持。

  三個接口分別是:

  1、TransactionDefinition:定義了事務的屬性。

    a、事務傳播行為

    b、事務隔離級別

    c、事務超時

    d、是否是只讀    

源碼如下:

public interface TransactionDefinition {
    int PROPAGATION_REQUIRED = 0;
    int PROPAGATION_SUPPORTS = 1;
    int PROPAGATION_MANDATORY = 2;
    int PROPAGATION_REQUIRES_NEW = 3;
    int PROPAGATION_NOT_SUPPORTED = 4;
    int PROPAGATION_NEVER = 5;
    int PROPAGATION_NESTED = 6;
    int ISOLATION_DEFAULT = -1;
    int ISOLATION_READ_UNCOMMITTED = 1;
    int ISOLATION_READ_COMMITTED = 2;
    int ISOLATION_REPEATABLE_READ = 4;
    int ISOLATION_SERIALIZABLE = 8;
    int TIMEOUT_DEFAULT = -1;

    int getPropagationBehavior();

    int getIsolationLevel();

    int getTimeout();

    boolean isReadOnly();

    String getName();
} 

  2、TransactionStatus:描述事務具體的運行狀態,繼承了SavepointManager接口

public interface TransactionStatus extends SavepointManager, Flushable {
    boolean isNewTransaction();

    boolean hasSavepoint();

    void setRollbackOnly();

    boolean isRollbackOnly();

    void flush();

    boolean isCompleted();
} 

  

public interface SavepointManager {
    Object createSavepoint() throws TransactionException;

    void rollbackToSavepoint(Object var1) throws TransactionException;

    void releaseSavepoint(Object var1) throws TransactionException;
} 

  

boolean isNewTransaction():判斷當前事務是否是一個新事務,如果返回false,說明當前事務已存在,或者該操作沒在事務環境中。

boolean hasSavepoint():判斷當前事務是否有保存點。

void setRollbackOnly():設置當前事務為rollback-only模式,事務管理器接收到這個指令之後會回滾事務

boolean isRollbackOnly():判斷當前事務是否是rollback-only

void flush():用於刷新底層會話的修改到數據庫

boolean isCompleted():判斷當前事務是否已經結束

Object createSavepoint():創建保存點

void rollbackToSavepoint(Object var1) :使事務回滾到保存點上,回滾之後保存的自動釋放

void releaseSavepoint(Object var1) :釋放指定保存點

3、PlatFormTransactionManager: 事務管理器

public interface PlatformTransactionManager {
    TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;

    void commit(TransactionStatus var1) throws TransactionException;

    void rollback(TransactionStatus var1) throws TransactionException;
}

  

TransactionStatus getTransaction(TransactionDefinition var1):事務管理器根據TransactionDefinition描述的事務屬性創建一個事務,並返回一個 TransactionStatus用來具體描述事務的運行狀態。

void commit(TransactionStatus var1):事務管理器根據事務的運行狀態對事務進行提交操作,如果該事物被設置為rollback-only,則將事務回滾

void rollback(TransactionStatus var1): 事務管理器對事務進行回滾操作。

工作中使用Mybatis持久層框架,Mybatis事務管理器的實現類是

org.springframework.jdbc.datasource.DataSourceTransactionManager

需要在spring配置文件進行配置

技術分享

3、使用XML配置聲明式事務

Spring使用XML配置聲明式事務分為兩種,一種用TransactionProxyFactoryBean,一種用aop/tx,由於早期Spring沒有aop的特性,所以用代理工廠的方式配置事務,現在這種方式已經很少使用,所以不研究了。下面研究下使用aop/tx,配置事務。

首先定義一個類。

@Service
@Transactional
public class BbtForum{
    public ForumDao forumDao;
    public TopicDao topicDao;
    public PostDao  postDao;
    public void addTopic(Topic topic){
        topic.addTopic(topic);
        postDao.addPost(topic.getPost());
    }
    public Forum getForum(int forumId){
        return forumDao.getForum(forumId);
    }
    public void updateForum(Forum forum){
        forumDao.updateForum(forum);
    }
    public int getForumNum(){
        return forumDao.getForumNum();
    }
} 

  技術分享技術分享

技術分享

    Spring通過<aop:pointcut>來指定需要織入增強的切點,此處定義的是該包下所有類的所有方法,通過<tx:advice>聲明增強,此處需要事務管理器,通過<tx:method>為加入事務的方法指定屬性,<tx:method>的屬性有name,propagation,isolation,timeout,read-only,rollback-for,non-rollback-for

  

4、使用註解的方式配置事務

這也是我平時最常用的方式,使用註解配置事務需要先在配置文件中加載註解驅動

技術分享

  註解驅動配置後,就可以用@Transacational註解來配置事務,該註解有以下屬性可以配置:propagation,isolation,read-only,timeout,rollbackFor,noRollbackFor,rollbackForClassName,noRollBackForClassName

  @Transacational註解可以用在類上,代表該類所有的方法都運行在事務環境中,也可以單獨配置在方法上,給方法設置特定的事務環境。但是一般不標註在接口或抽象類上,因為@Transacational不能被繼承。

技術分享

Spring對事務的支持