spring事物--04原始碼分析-事務處理攔截器的實現分析
阿新 • • 發佈:2018-12-18
事務處理攔截器的實現分析
通過上面的分析,很明確spring在事務方面aop是怎麼玩的了。那麼真正要處理事務是ProxyFactory.getObject() 方法返回的代理物件,通過呼叫代理物件的方法時,攔截器有一個invoker() 方法會被回撥(aop的玩法)。
TransactionInterceptor.invoke() 方法原始碼:
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... //呼叫父類TransactionAspectSupport的方法 return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); } @Nullable 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(); //獲取事務配屬性 final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); //根據TransactionProxyFactoryBean 的配置資訊,獲取事務處理器 final PlatformTransactionManager tm = determineTransactionManager(txAttr); //方法全限定名,如:com.masz.springtest.transaction.TransactionTXNameSpaceTest.add final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); /** * 區分不同型別的PlatformTransactionManager,因為它們的呼叫方式不同 * CallbackPreferringPlatformTransactionManager 需要回調函式來實現事務的建立和提交, * 對於其它的事務管理器,如 DataSourceTransactionManager 就不需要通過回撥的方式來使用 * */ 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 { //把與執行緒繫結的TransactionInfo 設定為OldTransationInfo 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. // RuntimeException 會導致事務回滾 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 { //把與執行緒繫結的TransactionInfo 設定為OldTransationInfo 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對aop事務的封裝,
下來說明spring 是如何提供宣告式事務處理的,spring封裝了什麼。
待續:spring 是如何提供宣告式事務處理的,spring封裝了什麼。