事務屬性定義接口
TransactionDefinition是事務屬性定義接口,保存事務定義的各種屬性,如超時時間、隔離級別、傳播屬性等。
public interface TransactionDefinition {
//獲取事務傳播類型
int getPropagationBehavior();
//獲取事務隔離級別
int getIsolationLevel();
//獲取事務超時時間
int getTimeout();
//事務的只讀性
boolean isReadOnly();
//獲取事務名稱
String getName();
}
事務實例接口
TransactionStatus是事務實例接口,表示了當前事務在內存中的一個實例,從名字來看保存了事務的運行狀態信息。
AbstractTransactionStatus是抽象實現,DefaultTransactionStatus是事務實例的默認實現。
事務管理器
PlatformTransactionManager是Spring事務的核心接口,一般不會直接使用該接口,應用程序可以直接用TransactionTemplate或者AOP進行事務操作。AbstractPlatformTransactionManager是PlatformTransactionManager的抽象類實現。
public interface PlatformTransactionManager {
//根據事務指定的策略獲取激活的事務或者重新創建一個事務。
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
//提交事務
void commit(TransactionStatus status) throws TransactionException;
//回滾事務
void rollback(TransactionStatus status) throws TransactionException;
}
AbstractPlatformTransactionManager定義事務實現的骨架。
獲取事務
getTransaction(TransactionDefinition definition)主要邏輯是首先獲取當前線程的事務:
Object transaction = doGetTransaction();
注意doGetTransaction是個鉤子方法,負責子類方法的回調,凡是以do開頭的方法都類似,後續不在贅述。
如果當前線程已經存在事務,則handleExistingTransaction(definition, transaction, debugEnabled),這個方法根據配置的事務策略處理存在的事務:
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
return handleExistingTransaction(definition, transaction, debugEnabled);
}
如果當前線程不存在事務,則開啓新事務:
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
}
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 ex) {
resume(null, suspendedResources);
throw ex;
}
catch (Error err) {
resume(null, suspendedResources);
throw err;
}
我們選擇DataSourceTransactionManager的doBegin看看,裏面設置事務爲手動提交模式,然後激活當前事務:
// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
// so we don't want to do it unnecessarily (for example if we've explicitly
// configured the connection pool to set it already).
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
if (logger.isDebugEnabled()) {
logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
con.setAutoCommit(false); //設置爲手動提交
}
txObject.getConnectionHolder().setTransactionActive(true);
事務提交
主要實現方法是processCommit,在事務提交之前還做了其他額外準備操作,然後執行doCommit方法,出錯時不會進行資源清理操作,不做回滾操作,回滾操作由調用者發起。
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
boolean beforeCompletionInvoked = false;
try {
prepareForCommit(status);
triggerBeforeCommit(status);
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
boolean globalRollbackOnly = false;
if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
globalRollbackOnly = status.isGlobalRollbackOnly();
}
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Releasing transaction savepoint");
}
status.releaseHeldSavepoint();
}
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction commit");
}
doCommit(status);
}
// Throw UnexpectedRollbackException if we have a global rollback-only
// marker but still didn't get a corresponding exception from commit.
if (globalRollbackOnly) {
throw new UnexpectedRollbackException(
"Transaction silently rolled back because it has been marked as rollback-only");
}
}
catch (UnexpectedRollbackException ex) {
// can only be caused by doCommit
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
throw ex;
}
...
事務回滾
public final void rollback(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
processRollback(defStatus);
}
事務同步管理器
TransactionSynchronizationManager關鍵實現是依賴ThreadLocal。各種數據庫資源保存在各自線程的副本中,保證線程安全,典型的用空間換時間的做法。
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<Map<Object, Object>>("Transactional resources");
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
new NamedThreadLocal<Set<TransactionSynchronization>>("Transaction synchronizations");
private static final ThreadLocal<String> currentTransactionName =
new NamedThreadLocal<String>("Current transaction name");
private static final ThreadLocal<Boolean> currentTransactionReadOnly =
new NamedThreadLocal<Boolean>("Current transaction read-only status");
private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
new NamedThreadLocal<Integer>("Current transaction isolation level");
private static final ThreadLocal<Boolean> actualTransactionActive =
new NamedThreadLocal<Boolean>("Actual transaction active");