Spring事务tx源码分析(一)

 2019-11-02 21:06  阅读(1359)
文章分类:Spring boot

在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则进行回滚。


来源:http://ddrv.cn

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Spring事务tx源码分析(一)

相关推荐