spring声明式事务源码剖析(中)

TransactionInterceptor这个类我们在上一篇中已经认识了,这一篇我们来看一下,它是如何完成事务的拦截。spring代码版本v.4.2.4.RELEASE.

  1. TransactionInterceptor.invoke

    @Override
    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, new InvocationCallback() {
            @Override
            public Object proceedWithInvocation() throws Throwable {
                return invocation.proceed();
            }
        });
    }
    
  2. TransactionAspectSupport.invokeWithinTransaction

    protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
                throws Throwable {
    
            // If the transaction attribute is null, the method is non-transactional.
            final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
            final PlatformTransactionManager tm = determineTransactionManager(txAttr);
            final String joinpointIdentification = methodIdentification(method, 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.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 {
                    Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
                            new TransactionCallback<Object>() {
                                @Override
                                public Object doInTransaction(TransactionStatus 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.
                                            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();
                }
            }
        }
    

    这个方法开启事务,执行业务方法,关闭事务,返回业务执行结果;

  3. TransactionAspectSupport.createTransactionIfNecessary

    这个方法开启事务,事务的开启最终转嫁给 PlatformTransactionManager。对于一般的开发我们都应用单个关系型数据库,所以对应的PlatformTransactionManger为 DataSourceTransactionManager

  4. DataSourceTransactionManager.getTransaction

    该方法其父类中实现

  5. AbstractPlatformTransactionManager.getTransaction

    /**
     * This implementation handles propagation behavior. Delegates to
     * {@code doGetTransaction}, {@code isExistingTransaction}
     * and {@code doBegin}.
     * @see #doGetTransaction
     * @see #isExistingTransaction
     * @see #doBegin
     */
    @Override
    public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
        Object transaction = doGetTransaction();
    
    // Cache debug flag to avoid repeated checks.
    boolean debugEnabled = logger.isDebugEnabled();
    
    if (definition == null) {
        // Use defaults if no transaction definition given.
        definition = new DefaultTransactionDefinition(); //事务不存在时
    }
    
    if (isExistingTransaction(transaction)) { //事务已存在
        // Existing transaction found -> check propagation behavior to find out how to behave.
        return handleExistingTransaction(definition, transaction, debugEnabled);
    }
    
    // Check definition settings for new transaction.
    if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
        throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
    }
    
    // No existing transaction found -> check propagation behavior to find out how to proceed.
    //事务传播判断
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
        throw new IllegalTransactionStateException(
                "No existing transaction found for transaction marked with propagation 'mandatory'");
    }
    
    else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
            definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
            definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
        SuspendedResourcesHolder suspendedResources = suspend(null);
        if (debugEnabled) {
            logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
        }
        try {
            boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
            DefaultTransactionStatus status = newTransactionStatus(
                    definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
            doBegin(transaction, definition);  //开启事务
            prepareSynchronization(status, definition);//同步事务
            return status;
        }
        catch (RuntimeException ex) {
            resume(null, suspendedResources);
            throw ex;
        }
        catch (Error err) {
            resume(null, suspendedResources);
            throw err;
        }
    }
    else {
        // Create "empty" transaction: no actual transaction, but potentially synchronization.
        if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
            logger.warn("Custom isolation level specified but no actual transaction initiated; " +
                    "isolation level will effectively be ignored: " + definition);
        }
        boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
        return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
    }
    

    }

方法定义如上.在学习spring事务时,需要注意如下几个类或接口

TransactionDefinition:事务接口
TransactionAttribute    事务接口扩展
TransactionStatus   事务状态
PlatformTransactionManager 统一事务管理平台

对于如上的spring事务传播机制进行总结如下(我相信很多人都看过这个表格)

事务传播类型 行为
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行
PROPAGATION_MANDATORY 使用当前的事务,如果没有事务,则抛出异常
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起;注意区分PROPAGATION_REQUIRES_NEW
PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常
PROPAGATION_REQUIRED 如果当前没有事务,则新建一个事务;如果已经存在一个事务中,则加入到这个事务中
PROPAGATION_REQUIRES_NEW 如果当前存在事务,把当前事务挂起,并新建事务,在支持savepoint的platform可以进行事务部分回滚;注意区分PROPAGATION_NOT_SUPPORTED
PROPATATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROGATION_REQUIRED类似的操作
  1. AbstractPlatformTransactionManager.doBegin(Object transaction, TransactionDefinition definition)

    它的实现在子类DataSourceTransactionManager

  2. DataSourceTransactionManager.doBegin

    这个方法获取Connection 并打开事务,它依赖于关系数据库的事务支持程度,所以说spring不重新发明轮子。

关于应用xml配置的声明式事务,已经至此完毕,对于应用注解式的事务管理,我们下篇再剖析。

猜你喜欢

转载自blog.csdn.net/zhurhyme/article/details/77650488
今日推荐