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);
// If the transaction attribute is null, the method is non-transactional. finalTransactionAttributetxAttr= getTransactionAttributeSource().getTransactionAttribute(method, targetClass); finalPlatformTransactionManagertm= determineTransactionManager(txAttr); finalStringjoinpointIdentification= methodIdentification(method, targetClass);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. TransactionInfotxInfo= createTransactionIfNecessary(tm, txAttr, joinpointIdentification); ObjectretVal=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. try { Objectresult= ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, newTransactionCallback<Object>() { @Override public Object doInTransaction(TransactionStatus status) { TransactionInfotxInfo= 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 { thrownewThrowableHolderException(ex); } } else { // A normal return value: will lead to a commit. returnnewThrowableHolder(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(); } } }