通過上一篇《從@Transactional註解看Spring事務》,已經大概瞭解了事務中的基本使用。這一篇,小編跟大家一起通過Spring中幾個重要源碼類來增加對Spring事務的瞭解;
在Spring中實現事務需要很多類的配合,但這裏小編主要分析這幾個類:TransactionDefinition、PlatformTransactionManager、TransactionStatus、TransactionInceptor;
▶ TransactionDefinition
從字面上來看,這個類主要是做事務的定義。實際上也確實是這樣,它是對事務定義的最頂級接口,主要是定義事務隔離級別、事務傳播性和事務的只讀性等。
TransactionDefinition部分代碼:
public interface TransactionDefinition {
int PROPAGATION_REQUIRED = 0;
int PROPAGATION_SUPPORTS = 1;
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 = Connection.TRANSACTION_READ_UNCOMMITTED;
int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;
int TIMEOUT_DEFAULT = -1;
// 獲取事務的隔離級別
int getPropagationBehavior();
//獲取隔離級別
int getIsolationLevel();
//是否超時
int getTimeout();
//校驗當前事務是隻讀
boolean isReadOnly();
@Nullable
String getName();
}
結合類(接口)與類(接口)之間的關係,小編整理出來一張圖,用來明確TransactionDefinition這個接口不可撼動的地位:
從上圖中,我們可以看到在實現TranscationDefinition這個接口的有DefaultTransactionDefinition類,在這個類中,對TransactionDefinition中的方法進行簡單實現;
▶ PlatformTransactionManager
和TransactionDefinition一樣,都是接口,並且都是在自己的領域內的頂級接口;PlatformTransactionManager是事務管理器的頂級接口,各持久化框架要想接入spring的事務管理,都必須自行提供該接口的實現。
在這個接口的衆多實現類中,有一個不容忽視的類AbstractPlatformTransactionManager;
爲什麼說它不容忽視呢?在這個類中實現了spring標準的事務流:
綜合上圖我們很容易得知,在該類中,定義並實現了很多與事務直接相關的方法,在該類中,除了對PlatformTransactionManager中commit(TransactionStatus status),rollback(TransactionStatus status),getTransaction(@Nullable TransactionDefinition definition)三個方法進行重載之外,定義了許多 **TransactionSynchronization、**ValidateExistingTranscation*、**rollbackOnCommitFailure、handleExistingTransaction等的私有或受保護的方法;這些方法覆蓋了事務狀態、對存在的事務的有效性和處理、提交失敗的事務處理等方面,正因爲如此,纔會在上文中提到“在這個類中實現了spring標準的事務流”;
☞ getTransaction(TransactionDefinition definition):只要是對事務傳播行爲的處理
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
Object transaction = doGetTransaction();
// Cache debug flag to avoid repeated checks.
boolean debugEnabled = logger.isDebugEnabled();
//如果傳入的事務定義爲空,則初始化一個DefaultTransactionDefinition類
if (definition == null) {
// Use defaults if no transaction definition given.
definition = new DefaultTransactionDefinition();
}
//如果已經存在事務,調用方法處理當前存在的事務
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
return handleExistingTransaction(definition, transaction, debugEnabled);
}
// Check definition settings for new transaction.
if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
}
// No existing transaction found -> check propagation behavior to find out how to proceed.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
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 | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + definition);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
}
}
在方法實現的最後,prepareTransactionStatus方法需要引起我們的注意,最終該方法會調用到一個同名方法:
/**
* status.isNewSynchronization是判斷一個新的事務鎖定是否已經開啓;
*/
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
if (status.isNewSynchronization()) {
TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?
definition.getIsolationLevel() : null);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
TransactionSynchronizationManager.initSynchronization();
}
}
因此,getTransaction方法其實就是對我們平時對事務設置的傳播行爲進行的分析和處理。{提前透漏,該方法是事務實現的直接被調用方,稍後會講到}
☞ commit(TransactionStatus status):
@Override
public final void commit(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;
//如果屬性爲只是當前事務回滾,則執行當前事務的回滾
if (defStatus.isLocalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Transactional code has requested rollback");
}
processRollback(defStatus, false);
return;
}
//如果事務的回滾屬性爲全局回滾
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
}
processRollback(defStatus, true);
return;
}
//將事務的當前狀態,提交事務
processCommit(defStatus);
}
當我們使用編程式事務時手動提交事務的實現就是這個commit方法,它的作用,要麼提交當前事務,要麼回滾;
其中,defStatus.isLocalRollbackOnly()變量的實際值:是根據事務傳播行爲的不同而具備的回滾當前事務或者整個事務的flag;舉個栗子,nested事務,回滾的是當前事務,而不影響整體的事務流程;required事務,則表示要回滾的是整個事務流程;
☞ rollback:
該方法的實現邏輯使用僞代碼來表示爲:
· 是否有節點
有--回滾到當前保存的事務節點
· 是否爲新事務
是--回滾當前事務
· 其他情況
· 是否有事務
……
因此,該方法和commit方法是相輔相承的。
☞ handleExistingTransaction :該方法主要是爲一個存在的事務創建事務狀態;
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled) throws TransactionException {
//如果事務定義中沒有事務的隔離級別,拋異常
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
//事務定義中隔離級別爲不支持事務
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);
}
//事務隔離級別爲開啓一個新事務
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
}
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 | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
}
//事務隔離級別爲嵌套事務
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
if (!isNestedTransactionAllowed()) {
throw new NestedTransactionNotSupportedException(
"Transaction manager does not allow nested transactions by default - " +
"specify 'nestedTransactionAllowed' property with value 'true'");
}
if (debugEnabled) {
logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
}
//在嵌套事務中使用節點,則創建並且保持節點
if (useSavepointForNestedTransaction()) {
// Create savepoint within existing Spring-managed transaction,
// through the SavepointManager API implemented by TransactionStatus.
// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint();
return status;
}
//鎖定事務
else {
// Nested transaction through nested begin and commit/rollback calls.
// Usually only for JTA: Spring synchronization might get activated here
// in case of a pre-existing JTA transaction.
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, null);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
}
// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
if (debugEnabled) {
logger.debug("Participating in existing transaction");
}
if (isValidateExistingTransaction()) {
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
Constants isoConstants = DefaultTransactionDefinition.constants;
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] specifies isolation level which is incompatible with existing transaction: " +
(currentIsolationLevel != null ?
isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
"(unknown)"));
}
}
if (!definition.isReadOnly()) {
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] is not marked as read-only but existing transaction is");
}
}
}
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
▶ TransactionTemplate
該類繼承了DefaultTransactionDefinition,簡化了事務的劃分和事務異常的處理;在該類中,引用了PlatformTransactionManager,核心方法是execute:
@Override
@Nullable
public <T> T execute(TransactionCallback<T> action) throws TransactionException {
Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");
//如果實現了CallbackPreferringPlatformTransactionManager,直接調用execute方法(由於execute方法的出參是泛型,必須有具體類做強轉)
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
}
else {
//如果不是,獲取當前事務管理器的事務狀態
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try {
// 這個方法我還沒有明確調用關係,待後續!!!!!!!
result = action.doInTransaction(status);
}
catch (RuntimeException | Error ex) {
// Transactional code threw application exception -> rollback
rollbackOnException(status, ex);
throw ex;
}
catch (Throwable ex) {
// Transactional code threw unexpected exception -> rollback
rollbackOnException(status, ex);
throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
}
this.transactionManager.commit(status);
return result;
}
}
▶TransactionStatus:
表示事務的狀態,代表一個新建的或者已經存在的事務,控制事務執行和查詢事務狀態;它是從SavePointManager接口派生的,但需要注意的是:節點管理只對基礎的事務管理起作用;
▶ TransactionInterceptor
我們都知道Spring的事務是採用AOP(切面)的方式實現的,提起事務實現我們就不得不提及到TransactionAspectSupport和它的相關類;
TransactionAspectSupport是提供事務切面的抽象類(也可以理解成是一個基礎類,比如TransactionInterceptor),該類包括spring的基礎事務api;
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
該類實現了BeanFactoryAware和InitializingBean,在該類所定義的每一個方法都有自己的實現,但由於要做切面,它的子類都必須序列化,否則無法使用,因此該類是抽象的;
該類實現的BeanFactoryAware的作用,主要是爲了能夠使用spring中的bean做配置:
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory var1) throws BeansException;
}
該類中實現的InitializingBean,主要是在bean實例化完成後調用,完成初始化檢查,查看當前對象是否完整,是否可用;而對對象的可用性檢查則是在afterPropertiesSet方法中完成;
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
作爲TransactionAspectSupport的子類,是線程安全的,它按照正確的順序調用了超類中的方法(比如:invokeWithinTransaction):
@Override
@Nullable
public Object invoke(final MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); //此處調用爲超類中的方法
}
TransactionAspectSupport.invokeWithinTransaction 代碼如下:
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
//獲取事務的屬性源
TransactionAttributeSource tas = getTransactionAttributeSource();
//根據事務屬性源,獲取事務屬性(屬性是配置的,詳見setTransactionAttributes(Properties transactionAttributes)方法)
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 獲取事務屬性要使用的事務管理器
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
//獲取方法標識,爲子類的切面提供調用條件
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
//如果事務屬性是空,或者並不是CallbackPreferringPlatformTransactionManager的實現類
//該種情況通常是我們使用的聲明式事務的執行邏輯
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
//根據事務屬性、節點定義信息和事務管理器創建事務
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
commitTransactionAfterReturning(txInfo);
return retVal;
}
// 編程式事務的執行邏輯
else {
final ThrowableHolder throwableHolder = new ThrowableHolder();
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
try {
return invocation.proceedWithInvocation();
}
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {
throw new ThrowableHolderException(ex);
}
}
else {
// A normal return value: will lead to a commit.
throwableHolder.throwable = ex;
return null;
}
}
finally {
cleanupTransactionInfo(txInfo);
}
});
// Check result state: It might indicate a Throwable to rethrow.
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
}
return result;
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
catch (TransactionSystemException ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);
}
throw ex2;
}
catch (Throwable ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw ex2;
}
}
}
該篇主要是先對Spring事務中的幾個重要類(接口)有個大致的瞭解,後續將會對它們在Spring事務中的協作進行深入解析;