Spring事务源码(1)-TransactionInterceptor

事务执行过程

事务执行过程.jpg

如图:a b 两个对象分别都是用了@Transactional注解开启声明式事务
问题一:如果 b 方法自己捕获了异常,那 ab 事务会提交吗?
问题二:如果 a 方法对b方法捕获异常 那 ab 事务会提交吗?
问题三:如果把条件改成 @Transactional(propagation = Propagation.REQUIRES_NEW) 呢?重复上面一 ,二 问题

/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.transaction.interceptor;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Properties;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.lang.Nullable;
import org.springframework.transaction.PlatformTransactionManager;

/**
 * AOP Alliance MethodInterceptor for declarative transaction
 * management using the common Spring transaction infrastructure
 * ({@link org.springframework.transaction.PlatformTransactionManager}).
 *
 * 

Derives from the {@link TransactionAspectSupport} class which * contains the integration with Spring's underlying transaction API. * TransactionInterceptor simply calls the relevant superclass methods * such as {@link #invokeWithinTransaction} in the correct order. * *

TransactionInterceptors are thread-safe. * * @author Rod Johnson * @author Juergen Hoeller * @see TransactionProxyFactoryBean * @see org.springframework.aop.framework.ProxyFactoryBean * @see org.springframework.aop.framework.ProxyFactory */ 用于声明性事务的AOP联盟方法拦截器 *使用公共Spring事务基础设施的管理 * ({@link org.springframework.transaction.PlatformTransactionManager})。 * *

派生自{@link TransactionAspectSupport}类 *包含与Spring底层事务API的集成。 * TransactionInterceptor简单地调用相关的超类方法 *如{@link #invokeWithinTransaction},按正确的顺序。 * *

TransactionInterceptors是线程安全的。 @SuppressWarnings("serial") public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable { /** * Create a new TransactionInterceptor. *

Transaction manager and transaction attributes still need to be set. * @see #setTransactionManager * @see #setTransactionAttributes(java.util.Properties) * @see #setTransactionAttributeSource(TransactionAttributeSource) */ public TransactionInterceptor() { } /** * Create a new TransactionInterceptor. * @param ptm the default transaction manager to perform the actual transaction management * @param attributes the transaction attributes in properties format * @see #setTransactionManager * @see #setTransactionAttributes(java.util.Properties) */ public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) { setTransactionManager(ptm); setTransactionAttributes(attributes); } /** * Create a new TransactionInterceptor. * @param ptm the default transaction manager to perform the actual transaction management * @param tas the attribute source to be used to find transaction attributes * @see #setTransactionManager * @see #setTransactionAttributeSource(TransactionAttributeSource) */ public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) { setTransactionManager(ptm); setTransactionAttributeSource(tas); } @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); } //--------------------------------------------------------------------- // Serialization support //--------------------------------------------------------------------- private void writeObject(ObjectOutputStream oos) throws IOException { // Rely on default serialization, although this class itself doesn't carry state anyway... oos.defaultWriteObject(); // Deserialize superclass fields. oos.writeObject(getTransactionManagerBeanName()); oos.writeObject(getTransactionManager()); oos.writeObject(getTransactionAttributeSource()); oos.writeObject(getBeanFactory()); } private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { // Rely on default serialization, although this class itself doesn't carry state anyway... ois.defaultReadObject(); // Serialize all relevant superclass fields. // Superclass can't implement Serializable because it also serves as base class // for AspectJ aspects (which are not allowed to implement Serializable)! setTransactionManagerBeanName((String) ois.readObject()); setTransactionManager((PlatformTransactionManager) ois.readObject()); setTransactionAttributeSource((TransactionAttributeSource) ois.readObject()); setBeanFactory((BeanFactory) ois.readObject()); }

TransactionAspectSupport


    /**
     * General delegate for around-advice-based subclasses, delegating to several other template
     * methods on this class. Able to handle {@link CallbackPreferringPlatformTransactionManager}
     * as well as regular {@link PlatformTransactionManager} implementations.
     * @param method the Method being invoked
     * @param targetClass the target class that we're invoking the method on
     * @param invocation the callback to use for proceeding with the target invocation
     * @return the return value of the method, if any
     * @throws Throwable propagated from the target invocation
     */
    @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);
        final PlatformTransactionManager tm = determineTransactionManager(txAttr);
        final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
                //如果@Transaction注解没有配置相关属性 或者
                //tm 不是CallbackPreferringPlatformTransactionManager类型 
        if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
            // Standard transaction demarcation with getTransaction and commit/rollback calls.
                        //获取事务调用commit/rollback 进行标准事务划分
            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 ThreadLocal。
                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;
            }
        }
    }

completeTransactionAfterThrowing
处理一个可抛出的,完成事务。
我们可以提交或回滚,这取决于配置。

/**
     * Handle a throwable, completing the transaction.
     * We may commit or roll back, depending on the configuration.
     * @param txInfo information about the current transaction
     * @param ex throwable encountered
处理一个可抛出的,完成事务。  
我们可以提交或回滚,这取决于配置。  
     */
    protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
               
        if (txInfo != null && txInfo.getTransactionStatus() != null) {
            if (logger.isTraceEnabled()) {
                logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
                        "] after exception: " + ex);
            }
 // transactionAttribute 不为空,并且 抛出的异常 需要是RunTimeException/Error,如果是Exception 怎么办呢? 下面会解释 rollbackOn
            if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
                try {
//执行回滚逻辑                    txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
                }
                catch (TransactionSystemException ex2) {
                    logger.error("Application exception overridden by rollback exception", ex);
                    ex2.initApplicationException(ex);
                    throw ex2;
                }
                catch (RuntimeException | Error ex2) {
                    logger.error("Application exception overridden by rollback exception", ex);
                    throw ex2;
                }
            }
            else {
                // We don't roll back on this exception.
                // Will still roll back if TransactionStatus.isRollbackOnly() is true.                        // 不符合回滚的异常  但是当.isRollbackOnly() is true.依然会回滚
                try {
//执行提交逻辑                    txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
                }
                catch (TransactionSystemException ex2) {
                    logger.error("Application exception overridden by commit exception", ex);
                    ex2.initApplicationException(ex);
                    throw ex2;
                }
                catch (RuntimeException | Error ex2) {
                    logger.error("Application exception overridden by commit exception", ex);
                    throw ex2;
                }
            }
        }
    }

txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
AbstractPlatformTransactionManager.rollback 方法


    /**
     * This implementation of rollback handles participating in existing
     * transactions. Delegates to {@code doRollback} and
     * {@code doSetRollbackOnly}.
     * @see #doRollback
     * @see #doSetRollbackOnly
     */
    @Override
    public final void rollback(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;
        processRollback(defStatus, false);
    }

processRollback(defStatus, false);
回滚的处理方法 提交的方法里面也有调用到 先mark

/**
     * Process an actual rollback.
     * The completed flag has already been checked.
     * @param status object representing the transaction
     * @throws TransactionException in case of rollback failure
     */
    private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
        try {
            boolean unexpectedRollback = unexpected;

            try {
                              // 处理前准备
                triggerBeforeCompletion(status);
                              //如果存在保存点 则回退到上一个保存点
                if (status.hasSavepoint()) {
                    if (status.isDebug()) {
                        logger.debug("Rolling back transaction to savepoint");
                    }
                    status.rollbackToHeldSavepoint();
                }
                              //  如果是新事务则直接回滚
                else if (status.isNewTransaction()) {
                    if (status.isDebug()) {
                        logger.debug("Initiating transaction rollback");
                    }
                    doRollback(status);
                }
                else {
                                        // 如果是大事物
                    // Participating in larger transaction
                    if (status.hasTransaction()) {
     //1判断回滚标识 或者 2 参与事务失败后返回是否全局地将一个现有事务标记为仅回滚  
                        if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
                            if (status.isDebug()) {
                                logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
                            }
                                    //设置回滚标识
                            doSetRollbackOnly(status);
                        }
                        else {
                            if (status.isDebug()) {
                                logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
                            }
                        }
                    }
                    else {
                        logger.debug("Should roll back transaction but cannot - no transaction available");
                    }
                    // Unexpected rollback only matters here if we're asked to fail early
                    if (!isFailEarlyOnGlobalRollbackOnly()) {
                        unexpectedRollback = false;
                    }
                }
            }
            catch (RuntimeException | Error ex) {
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
                throw ex;
            }

            triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);

            // Raise UnexpectedRollbackException if we had a global rollback-only marker
            if (unexpectedRollback) {
                throw new UnexpectedRollbackException(
                        "Transaction rolled back because it has been marked as rollback-only");
            }
        }
        finally {
            cleanupAfterCompletion(status);
        }
    }
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());

AbstractPlatformTransactionManager.commit方法

/**
     * This implementation of commit handles participating in existing
     * transactions and programmatic rollback requests.
     * Delegates to {@code isRollbackOnly}, {@code doCommit}
     * and {@code rollback}.
     * @see org.springframework.transaction.TransactionStatus#isRollbackOnly()
     * @see #doCommit
     * @see #rollback
     */
    @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()) {
                      //如果回滚标识为true 则进行回滚
            if (defStatus.isDebug()) {
                logger.debug("Transactional code has requested rollback");
            }
            processRollback(defStatus, false);
            return;
        }
              *通过检查事务对象,  
*前提是后者实现了{@link SmartTransactionObject}接口。  
* 

如果事务本身被标记为仅回滚,则返回"true" *由事务协调器,例如在超时的情况下。 这种应该属于特例情况 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); }

processCommit(defStatus);
    /**
     * Process an actual commit.
     * Rollback-only flags have already been checked and applied.
     * @param status object representing the transaction
     * @throws TransactionException in case of commit failure
     */
    private void processCommit(DefaultTransactionStatus status) throws TransactionException {
        try {
            boolean beforeCompletionInvoked = false;

            try {
                boolean unexpectedRollback = false;
                prepareForCommit(status);
                triggerBeforeCommit(status);
                triggerBeforeCompletion(status);
                beforeCompletionInvoked = true;
                              //如果存在保存点则 释放保存点
                if (status.hasSavepoint()) {
                    if (status.isDebug()) {
                        logger.debug("Releasing transaction savepoint");
                    }
                    unexpectedRollback = status.isGlobalRollbackOnly();
                    status.releaseHeldSavepoint();
                }
                              
                else if (status.isNewTransaction()) {
//如果是新事务,则进行提交
                    if (status.isDebug()) {
                        logger.debug("Initiating transaction commit");
                    }
                    unexpectedRollback = status.isGlobalRollbackOnly();
                    doCommit(status);
                }
                else if (isFailEarlyOnGlobalRollbackOnly()) {
                    unexpectedRollback = status.isGlobalRollbackOnly();
                }

                // Throw UnexpectedRollbackException if we have a global rollback-only
                // marker but still didn't get a corresponding exception from commit.
                if (unexpectedRollback) {
                    throw new UnexpectedRollbackException(
                            "Transaction silently rolled back because it has been marked as rollback-only");
                }
            }
            catch (UnexpectedRollbackException ex) {
                // can only be caused by doCommit
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
                throw ex;
            }
            catch (TransactionException ex) {
                // can only be caused by doCommit
                if (isRollbackOnCommitFailure()) {
                    doRollbackOnCommitException(status, ex);
                }
                else {
                    triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
                }
                throw ex;
            }
            catch (RuntimeException | Error ex) {
                if (!beforeCompletionInvoked) {
                    triggerBeforeCompletion(status);
                }
                doRollbackOnCommitException(status, ex);
                throw ex;
            }

            // Trigger afterCommit callbacks, with an exception thrown there
            // propagated to callers but the transaction still considered as committed.
            try {
                triggerAfterCommit(status);
            }
            finally {
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
            }

        }
        finally {
  //最后清除
            cleanupAfterCompletion(status);
        }
    }




    /** 提交失败  则进行回滚
     * Invoke {@code doRollback}, handling rollback exceptions properly.
     * @param status object representing the transaction
     * @param ex the thrown application exception or error
     * @throws TransactionException in case of rollback failure
     * @see #doRollback
     */
    private void doRollbackOnCommitException(DefaultTransactionStatus status, Throwable ex) throws TransactionException {
        try {
            if (status.isNewTransaction()) {
                if (status.isDebug()) {
                    logger.debug("Initiating transaction rollback after commit exception", ex);
                }
                doRollback(status);
            }
            else if (status.hasTransaction() && isGlobalRollbackOnParticipationFailure()) {
                if (status.isDebug()) {
                    logger.debug("Marking existing transaction as rollback-only after commit exception", ex);
                }
                doSetRollbackOnly(status);
            }
        }
        catch (RuntimeException | Error rbex) {
            logger.error("Commit exception overridden by rollback exception", ex);
            triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
            throw rbex;
        }
        triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
    }

判断异常类型
txInfo.transactionAttribute.rollbackOn(ex)

 /**
  * Winning rule is the shallowest rule (that is, the closest in the
  * inheritance hierarchy to the exception). If no rule applies (-1),
  * return false.
  * @see TransactionAttribute#rollbackOn(java.lang.Throwable)
  */
 @Override
 public boolean rollbackOn(Throwable ex) {
     if (logger.isTraceEnabled()) {
         logger.trace("Applying rules to determine whether transaction should rollback on " + ex);
     }

     RollbackRuleAttribute winner = null;
     int deepest = Integer.MAX_VALUE;

     if (this.rollbackRules != null) {
         for (RollbackRuleAttribute rule : this.rollbackRules) {
             int depth = rule.getDepth(ex);
             if (depth >= 0 && depth < deepest) {
                 deepest = depth;
                 winner = rule;
             }
         }
     }

     if (logger.isTraceEnabled()) {
         logger.trace("Winning rollback rule is: " + winner);
     }

     // User superclass behavior (rollback on unchecked) if no rule matches.
     if (winner == null) {
         logger.trace("No relevant rollback rule found: applying default rules");            //如果没有配置则使用默认的  runtimeException / error
         return super.rollbackOn(ex);
     }

     return !(winner instanceof NoRollbackRuleAttribute);
 }


 /**
  * Return the depth of the superclass matching.
  * 

{@code 0} means {@code ex} matches exactly. Returns * {@code -1} if there is no match. Otherwise, returns depth with the * lowest depth winning. */ public int getDepth(Throwable ex) { return getDepth(ex.getClass(), 0); } //递归判断异常名字是否是@Transaction。rollbackFor配置的 private int getDepth(Class exceptionClass, int depth) { if (exceptionClass.getName().contains(this.exceptionName)) { // Found it! return depth; } // If we've gone as far as we can go and haven't found it... if (exceptionClass == Throwable.class) { return -1; } return getDepth(exceptionClass.getSuperclass(), depth + 1); }

你可能感兴趣的:(Spring事务源码(1)-TransactionInterceptor)