Spring事务tx源码分析(一)

在spring的tx源码中我们知道了,最后会通过AbstractAutoProxyCreator(其有一个父类是beanPostProcessor)的postProcessAfterInitialization(Object bean, String beanName)方法中的wrapIfNecessary方法去createProxy。其中生成jdk动态代理的类是JdkDynamicAopProxy类,其proceed()方法会执行到ReflectiveMethodInvocation类的proceed()方法,最后如果是事务,会调用TransactionInterceptor类的invoke方法,这个方法实现自MethodInterceptor类,这个是MethodInterceptor并不是cglib的MethodInterceptor类,所以要分清楚,调用的是其invoke方法:

    public Object invoke(final MethodInvocation invocation) throws Throwable {
        // Work out the target class: may be <code>null</code>.
        // 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.
        final TransactionAttribute txAttr =
                getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass);
        final PlatformTransactionManager tm = determineTransactionManager(txAttr);
        final String joinpointIdentification = methodIdentification(invocation.getMethod(), targetClass);

        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.proceed();
            }
            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 { Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
                        new TransactionCallback<Object>() {
                            public Object doInTransaction(TransactionStatus status) {
                                TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
                                try {
                                    return invocation.proceed();
                                }
                                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();
            }
        }
    }

如果是不是CallbackPreferringPlatformTransactionManager类则用第一种方式执行,否则走else方法,关于CallbackPreferringPlatformTransactionManager类

CallbackPreferringPlatformTransactionManger接口扩展自PlatformTransactionManger,根据以下的官方源码注释可知,该接口相当于是把事务的创建、提交和回滚操作都封装起来了,用户只需要传入TransactionCallback接口实例即可,而不是像使用PlatformTransactionManger接口那样,还需要用户自己显示调用getTransaction、rollback或commit进行事务管理。 作者:sherlockyb 链接:https://www.jianshu.com/p/80778d9d11f3 來源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 所以我们着重看下第一个方法,spring默认是以第一种方式执行的。

TransactionAttribute是异常回滚等参数:

public interface TransactionAttribute extends TransactionDefinition {

    /**
     * Return a qualifier value associated with this transaction attribute.
     * <p>This may be used for choosing a corresponding transaction manager
     * to process this specific transaction.
     */
    String getQualifier();

    /**
     * Should we roll back on the given exception?
     * @param ex the exception to evaluate
     * @return whether to perform a rollback or not
     */
    boolean rollbackOn(Throwable ex);
    
}

如果我们在@Transactional注解中配置了rollbackfor则会根据抛出的对应异常回滚,如果不配置默认情况下,会根据RuntimeException和Error进行回滚,源码如下:

protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {
        if (txInfo != null && txInfo.hasTransaction()) {
            if (logger.isTraceEnabled()) {
                logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
                        "] after exception: " + ex);
            }
            if (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 ex2) {
                    logger.error("Application exception overridden by rollback exception", ex);
                    throw ex2;
                }
                catch (Error err) {
                    logger.error("Application exception overridden by rollback error", ex);
                    throw err;
                }
            }
            else {
                // We don't roll back on this exception.
                // Will still roll back if TransactionStatus.isRollbackOnly() is true.
                try {
                    txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
                }

标红处,如果满足条件则进行回滚,否则进行commit,继续跟进:

    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");
            return super.rollbackOn(ex);
        }

如果配置了rollbackfor,会根据配置的rollbackfor进行回滚,rollbackfor中配置Throwable及其子类都可以,如果不配置则走如下代码:

    public boolean rollbackOn(Throwable ex) {
        return (ex instanceof RuntimeException || ex instanceof Error);
    }

默认如果是RuntimeException或者Error则进行回滚。

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/lz710117239/article/details/78990851
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞