從源碼看Spring事務

       通過上一篇《從@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的事務管理,都必須自行提供該接口的實現。

實現PlatformTransactionManager接口的類列表

      在這個接口的衆多實現類中,有一個不容忽視的類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事務中的協作進行深入解析;

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章