Spring事務(wù)攔截器為
org.springframework.transaction.interceptor.TransactionInterceptor
當(dāng)Spring對(duì)函數(shù)進(jìn)行事務(wù)攔截時(shí)装黑,會(huì)調(diào)用到TransactionInterceptor的invoke函數(shù)蛔外。
@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// 在事務(wù)中調(diào)用函數(shù)瘦赫,使函數(shù)支持事務(wù)
return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
@Override
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
});
}
invokeWithTransaction函數(shù)
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
throws Throwable {
// 數(shù)據(jù)準(zhǔn)備
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// 1.新建一個(gè)事務(wù)
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
//2.執(zhí)行業(yè)務(wù)代碼
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 異常處理
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {//
cleanupTransactionInfo(txInfo);
}
//3.提交事務(wù)
commitTransactionAfterReturning(txInfo);
return retVal;
}
//......其他代碼
}
整個(gè)事務(wù)處理過程中主要涉及到四個(gè)類
- TransactionAttribute
- PlatformTransactionManager
- TransactionStatus
- TransactionInfo
TransactionAttribute
public interface TransactionAttribute extends TransactionDefinition {
String getQualifier();
boolean rollbackOn(Throwable ex);
}
父類TransactionDefinition的定義
public interface TransactionDefinition {
int getIsolationLevel();
String getName();
int getPropagationBehavior();
boolean isReadOnly();
int getTimeout();
}
TransactionAttribute用于保存@Transactional注解上的屬性內(nèi)容称近。
PlatformTransactionManager
package org.springframework.transaction;
public interface PlatformTransactionManager {
//啟動(dòng)一個(gè)新事務(wù)
TransactionStatus getTransaction(TransactionDefinition definition)
//提交事務(wù)
void commit(TransactionStatus status)
//回滾事務(wù)
void rollback(TransactionStatus status)
}
PlatformTransactionManager是事務(wù)的具體操作類蓝牲,類似于JDBC的事務(wù)操作赌莺,使用PlatformTransactionManager進(jìn)行事務(wù)處理的偽代碼如下:
PlatformTransactionManager pm;
TransactionDefinition definition
//啟動(dòng)事務(wù)
TransactionStatus status=pm.getTransaction(definition);
try{
//處理業(yè)務(wù)邏輯
.....
//提交事務(wù)
pm.commit(status);
}catch(Throwable e){
//回滾事務(wù)
pm.rollback(status);
}
}
**TransactionStatus **
public interface TransactionStatus{
boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
void flush();
boolean isCompleted();
}
TransactionStatus表征一次事務(wù)操作司志。
TransactionInfo
protected final class TransactionInfo {
private final PlatformTransactionManager transactionManager;
private final TransactionAttribute transactionAttribute;
private final String joinpointIdentification;
private TransactionStatus transactionStatus;
private TransactionInfo oldTransactionInfo;
}
TransactionInfo將上面的三個(gè)類的內(nèi)容融合在一起,即當(dāng)前事務(wù)的相關(guān)信息降宅,
oldTransactionInfo為父事務(wù)的相關(guān)信息骂远。
Spring的事務(wù)的具體操作是PlatformTransactionManager,下面來(lái)具體說明PlatformTransactionManager得三個(gè)函數(shù)腰根。
1. getTransaction
TransactionStatus org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(TransactionDefinition definition)
getTransaction函數(shù)的業(yè)務(wù)邏輯可簡(jiǎn)化為
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
//1.獲取當(dāng)前的事務(wù)對(duì)象激才,如數(shù)據(jù)庫(kù)的connection對(duì)象
Object transaction = doGetTransaction();
//2.如果當(dāng)前的事務(wù)對(duì)象可用,根據(jù)當(dāng)前的傳遞方式额嘿,構(gòu)建TransactionStatus
if (isExistingTransaction(transaction)) {
return handleExistingTransaction(definition, transaction, debugEnabled);
}//3.如果不存在瘸恼,根據(jù)當(dāng)前的傳遞方式,構(gòu)建TransactionStatus
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
return status;
}
}
doGetTransaction函數(shù)
以PlatformTransactionManager的實(shí)現(xiàn)之一DataSourceTransactionManager為例册养,
protected Object doGetTransaction() {
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
txObject.setSavepointAllowed(isNestedTransactionAllowed());
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
TransactionSynchronizationManager.getResource是從線程上下文獲取數(shù)據(jù)庫(kù)連接信息东帅,如果存在,直接返回球拦,否則返回null.
isExistingTransaction
判斷當(dāng)前事務(wù)對(duì)象是否可用靠闭,在DataSourceTransactionManager中,只需要簡(jiǎn)單判斷ConnectionHolder是否可用即可刘莹。
protected boolean isExistingTransaction(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
return (txObject.getConnectionHolder() != null && txObject.getConnectionHolder().isTransactionActive());
}
handleExistingTransaction
是處理事務(wù)傳遞的關(guān)鍵類阎毅,在handleExistingTransaction中會(huì)根據(jù)當(dāng)前不同的事務(wù)傳遞方式創(chuàng)建不同的TransactionStatus
1.PROPAGATION_NEVER
當(dāng)前方法不應(yīng)在Transaction中運(yùn)行,如果存在已經(jīng)定義的Transaction則拋出異常点弯。
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
所以代碼中直接拋出異常
2.PROPAGATION_NOT_SUPPORTED
當(dāng)前方法不應(yīng)在Transaction中運(yùn)行扇调,如果存在已經(jīng)定義的Transaction,則該Transaction暫停(掛起)直至該方法運(yùn)行完畢抢肛。
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
if (debugEnabled) {
logger.debug("Suspending current transaction");
}
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
前面介紹過transaction是從上下文中獲取的狼钮,suspend函數(shù)掛起transaction的主要作用是將transaction的ConnectionHolder和事務(wù)的相關(guān)信息從線程上下文移除,這樣在業(yè)務(wù)代碼中獲取數(shù)據(jù)庫(kù)連接時(shí)捡絮,就不能從線程上下文中獲取到父事務(wù)的連接熬芜。
DefaultTransactionStatus prepareTransactionStatus(
TransactionDefinition definition, Object transaction, boolean newTransaction,
boolean newSynchronization, boolean debug, Object suspendedResources)
prepareTransactionStatus的作用有兩個(gè)
- 組裝DefaultTransactionStatus
- 如果newTransaction==true,更新當(dāng)前線程上下文福稳,保存當(dāng)前事務(wù)的信息涎拉,如事務(wù)隔離級(jí)別,傳遞方式等的圆。newTransaction還有另外一個(gè)作用:表示當(dāng)前事務(wù)需不需要進(jìn)行提交鼓拧,回滾操作。
當(dāng)傳遞方式為PROPAGATION_NOT_SUPPORTED時(shí)越妈,prepareTransactionStatus函數(shù)newTransaction參數(shù)的值為false季俩,不會(huì)更新線程上下文信息。業(yè)務(wù)代碼中獲取數(shù)據(jù)庫(kù)連接時(shí)會(huì)從數(shù)據(jù)源中獲取一個(gè)全新的connection使用梅掠。
3.Propagation.REQUIRES_NEW
當(dāng)前方法必須在新開的Transaction中運(yùn)行酌住。如果存在已經(jīng)定義的Transaction店归,則該已定義的Transaction暫停直至新開的Transaction執(zhí)行完畢。
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
catch (RuntimeException beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
catch (Error beginErr) {
resumeAfterBeginException(transaction, suspendedResources, beginErr);
throw beginErr;
}
}
操作分為3步:
- 掛起當(dāng)前事務(wù)
- 從數(shù)據(jù)源中獲取一個(gè)新的連接酪我,將connection的AutoCommit設(shè)置false.并將該connection綁定到當(dāng)前線程(doBegin函數(shù))消痛,以便業(yè)務(wù)代碼能獲取到該connection。
- 更新線程上下文關(guān)于當(dāng)前事務(wù)的相關(guān)信息都哭。
........
其他傳遞方式略
2.commit
commit 就比較簡(jiǎn)單肄满,主要做兩件事
- 如果當(dāng)前事務(wù)是newTransaction,提交事務(wù)
- 恢復(fù)當(dāng)前connection的屬性质涛,釋放connection
- 恢復(fù)被掛起的事務(wù)
提交connection
protected void doCommit(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Committing JDBC transaction on Connection [" + con + "]");
}
try {
//數(shù)據(jù)庫(kù)connection提交
con.commit();
}
catch (SQLException ex) {
throw new TransactionSystemException("Could not commit JDBC transaction", ex);
}
}
恢復(fù)connection屬性,釋放connection
protected void doCleanupAfterCompletion(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
// Remove the connection holder from the thread, if exposed.
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.unbindResource(this.dataSource);
}
// Reset connection.
Connection con = txObject.getConnectionHolder().getConnection();
try {
if (txObject.isMustRestoreAutoCommit()) {
con.setAutoCommit(true);
}
DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());
}
catch (Throwable ex) {
logger.debug("Could not reset JDBC Connection after transaction", ex);
}
if (txObject.isNewConnectionHolder()) {
if (logger.isDebugEnabled()) {
logger.debug("Releasing JDBC Connection [" + con + "] after transaction");
}
DataSourceUtils.releaseConnection(con, this.dataSource);
}
txObject.getConnectionHolder().clear();
}
恢復(fù)被掛起的事務(wù)
protected final void resume(Object transaction, SuspendedResourcesHolder resourcesHolder)
throws TransactionException {
if (resourcesHolder != null) {
Object suspendedResources = resourcesHolder.suspendedResources;
if (suspendedResources != null) {
doResume(transaction, suspendedResources);
}
List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
if (suspendedSynchronizations != null) {
TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);
TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);
doResumeSynchronization(suspendedSynchronizations);
}
}
}
3.rollback
與commit雷同掰担,不做解釋汇陆。
其他
Spring的Transactional注解是如何在mybatis中生效的?
Spring通過控制mybatis獲取的connection來(lái)起作用带饱。
mybatis的數(shù)據(jù)庫(kù)連接是從Mybatis的事務(wù)中獲取的
package org.apache.ibatis.executor;
public abstract class BaseExecutor{
protected Connection getConnection(Log statementLog) throws SQLException {
Connection connection = transaction.getConnection();
if (statementLog.isDebugEnabled()) {
return ConnectionLogger.newInstance(connection, statementLog, queryStack);
} else {
return connection;
}
}
}
mybatis的事務(wù)對(duì)象為:
org.apache.ibatis.transaction.Transaction
Transaction是有mybatis的事務(wù)工廠產(chǎn)生的
org.apache.ibatis.transaction.TransactionFactory
而mybatis默認(rèn)的事務(wù)工廠為
org.mybatis.spring.transaction.SpringManagedTransactionFactory
見下面mybatis代碼
package org.mybatis.spring;
public class SqlSessionFactoryBean{
protected SqlSessionFactory buildSqlSessionFactory(){
//部分代碼略..........
if (this.transactionFactory == null) {
this.transactionFactory = new SpringManagedTransactionFactory();
//部分代碼略.............
}
}
}
SpringManagedTransactionFactory生產(chǎn)的事務(wù)的類為
org.mybatis.spring.transaction.SpringManagedTransaction
SpringManagedTransaction的getConnection會(huì)調(diào)用到openConnection函數(shù)毡代。
private void openConnection() throws SQLException {
this.connection = DataSourceUtils.getConnection(this.dataSource);
this.autoCommit = this.connection.getAutoCommit();
this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource);
if (logger.isDebugEnabled()) {
logger.debug(
"JDBC Connection ["
+ this.connection
+ "] will"
+ (this.isConnectionTransactional ? " " : " not ")
+ "be managed by Spring");
}
}
DataSourceUtils.getConnection最終會(huì)調(diào)用到DataSourceUtils.doGetConnection函數(shù)
public static Connection doGetConnection(DataSource dataSource) throws SQLException {
Assert.notNull(dataSource, "No DataSource specified");
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
conHolder.requested();
if (!conHolder.hasConnection()) {
logger.debug("Fetching resumed JDBC Connection from DataSource");
conHolder.setConnection(dataSource.getConnection());
}
return conHolder.getConnection();
}
// Else we either got no holder or an empty thread-bound holder here.
logger.debug("Fetching JDBC Connection from DataSource");
Connection con = dataSource.getConnection();
if (TransactionSynchronizationManager.isSynchronizationActive()) {
logger.debug("Registering transaction synchronization for JDBC Connection");
// Use same Connection for further JDBC actions within the transaction.
// Thread-bound object will get removed by synchronization at transaction completion.
ConnectionHolder holderToUse = conHolder;
if (holderToUse == null) {
holderToUse = new ConnectionHolder(con);
}
else {
holderToUse.setConnection(con);
}
holderToUse.requested();
TransactionSynchronizationManager.registerSynchronization(
new ConnectionSynchronization(holderToUse, dataSource));
holderToUse.setSynchronizedWithTransaction(true);
if (holderToUse != conHolder) {
TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
}
}
return con;
}
上面的代碼首先會(huì)從線程上下文中獲取數(shù)據(jù)庫(kù)連接,如果不能獲取到勺疼,就直接從數(shù)據(jù)源中獲取教寂。