Spring對事務的支持
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對事務的支持