Spring聲明式事務註解之事務方法的執行

目錄

1. 說明

2. 執行事務方法

3. 總結


1. 說明

事務方法執行,原理跟AOP是一樣的,事務類被增強,然後執行事務方法的時候,其實是增強類執行目標方法和一個攔截器鏈,這裏的攔截器是TransactionInterceptor,然後在攔截器TransactionInterceptor裏面對目標方法進行事務管理;

2. 執行事務方法

  • 2.1 事務方法執行的調用鏈如下

  • 2.2 事務方法執行步驟

跟AOP原理一樣,先後執行順序如下:

》 com.yibai.spring.annotation.tx.service.PersonService.savePerson(Person) ;
》 org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor.intercept(Object, Method, Object[], MethodProxy)這裏會根據增強器轉換成攔截器,最後得到只有一個攔截器TransactionInterceptor的list集合的攔截器鏈;
》 創建CglibMethodInvocation,調用CglibMethodInvocation.proceed();
》 最後來到事務方法攔截器TransactionInterceptor的invoke方法中,完成目標類的事務管理;

  • 2.3 事務攔截關鍵方法分析        

       2.3.1 CglibAopProxy.DynamicAdvisedInterceptor.intercept(): 攔截事務方法的執行;

@Override
public Object proceed() throws Throwable {
	//	We start with an index of -1 and increment early.
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		// 事務方法本身
		return invokeJoinpoint();
	}

	// 獲取第一個攔截件TransactionInterceptor
	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		// Evaluate dynamic method matcher here: static part will already have
		// been evaluated and found to match.
		InterceptorAndDynamicMethodMatcher dm =
				(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
		if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
			return dm.interceptor.invoke(this);
		}
		else {
			// Dynamic matching failed.
			// Skip this interceptor and invoke the next in the chain.
			return proceed();
		}
	}
	else {
		// It's an interceptor, so we just invoke it: The pointcut will have
		// been evaluated statically before this object was constructed.
		// 執行TransactionInterceptor的invoke方法;
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

       2.3.2  事務攔截器TransactionInterceptor中的invoke(): 完成目標類的事務管理;

@Override
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, new InvocationCallback() {
		@Override
		public Object proceedWithInvocation() throws Throwable {
			return invocation.proceed();
		}
	});
}

其中invokeWithinTransaction()方法的實現如下:

protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
		throws Throwable {

	// If the transaction attribute is null, the method is non-transactional.
	// 從AnnotationTransactionAttributeSource中獲取事務信息(在解析事務類的時候已經被解析,這裏只是從緩存中獲取)
	final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
		
	// 根據事務信息txAttr獲取事務管理器,返回DataSourceTransactionManager
	final PlatformTransactionManager tm = determineTransactionManager(txAttr);
	final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

	if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
		// 標準事務
		// Standard transaction demarcation with getTransaction and commit/rollback calls.
		// 創建事務TransactionInfo並開啓
		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 {
		// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
		// 如果事務管理器是CallbackPreferringPlatformTransactionManager則走這裏
		try {
			Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
					new TransactionCallback<Object>() {
						@Override
						public Object doInTransaction(TransactionStatus 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.
									return new ThrowableHolder(ex);
								}
							}
							finally {
								cleanupTransactionInfo(txInfo);
							}
						}
					});

			// Check result: It might indicate a Throwable to rethrow.
			if (result instanceof ThrowableHolder) {
				throw ((ThrowableHolder) result).getThrowable();
			}
			else {
				return result;
			}
		}
		catch (ThrowableHolderException ex) {
			throw ex.getCause();
		}
	}
}

所以是在攔截器TransactionInterceptor的invoke方法中完成目標方法的事務管理;

3. 總結

事務方法執行,原理就是增強類執行事務方法和攔截器TransactionInterceptor,其中在TransactionInterceptor完成對事務方法的事務管理;

 

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