必威体育Betway必威体育官网
当前位置:首页 > IT技术

SpringTransaction源码解析(下)

时间:2019-09-03 02:41:06来源:IT技术作者:seo实验室小编阅读:85次「手机版」
 

transaction

前言:

通过上一篇博客 https://blog.csdn.net/qq_26323323/article/details/81948682 的分析, 我们从大的结构上分析了Spring事务的实现方式。

主要从通过Spring代理生成代理类,然后通过执行transactionInterceptor.invoke()方法,来完成Spring事务控制。

本文主要来分析TransactionInterceptor.invoke()究竟是如何完成Spring的事务控制的。

  

1.SpringTransaction的使用

请参考笔者另一篇博客 https://blog.csdn.net/qq_26323323/article/details/81908955 ,里面有详细用法 

2.传统的事务使用方式

public void test(){
    String url = "jdbc:mysql://localhost:3306/test";
    String username = "root";
    String password = "root";
    String sql = "update blog set name = ? where id=?";

    Connection connection = null;
    try {
        connection = DriverManager.getConnection(url, username, password);
        // 1.关闭自动提交,开启事务
        connection.setAutoCommit(false);
        Preparedstatement preparestatement = connection.prepareStatement(sql);
        prepareStatement.setString(1, "lucy");
        prepareStatement.setInt(2, 1);
        prepareStatement.executeUpdate();

        // 2.SQL正常执行,提交事务
        connection.commit();
    } catch (SQLException e) {
        try {
            // 3.执行出现错误,回滚事务
            connection.rollback();
        } catch (SQLException e1) {
            e1.printstacktrace();
        }
    }
}

  总结:通过传统的事务使用方式分析可知,事务的开启关闭是建立在java.sql.Connection的基础上。

  通过对Connection进行setAutoCommit(false)、commit()、rollback()操作来实现事务的开启、提交、回滚

实际Spring的事务控制也是基于此来实现的

3.Spring事务控制架构分析

通过上一篇博客的分析,我们知道事务控制是通过TransactionInterceptor.invoke()方法来实现的。下面我们来看一下这个方法的大体结构

public Object invoke(final MethodInvocation invocation) throws throwable {
    // 获取被代理类
    Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

    // 执行事务方法
    return invokewithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
        @Override
        public Object proceedWithInvocation() throws Throwable {
            return invocation.proceed();
        }
    });
}

// invokeWithinTransaction()
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
throws Throwable {

    // 1.获取该方法的事务属性 在1)中详细分析
    // 事务属性包括propagationBehavior(传播机制)/isolationLevel(隔离级别)/descriptor(方法类、名称)
    final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
    
    // 2.查找容器中的PlatformTransactionManager,用于管理事务 在2)中详细分析
    // 本例中使用的是datasourceTransactionManager
    final PlatformTransactionManager tm = determineTransactionManager(txAttr);
    
    // 3.获取被代理的类方法名称 在3)中详细分析
    // 例如在本例中就是jdbc.BlogServiceImpl.save
    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

    // 4.声明式事务的操作
    if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
        // 4.1 创建TransactionInfo(重要操作在这里)
        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.
            // 4.2 先执行其他Interceptor,执行完毕之后执行被代理类的方法
            retVal = invocation.proceedWithInvocation();
        }
        catch (Throwable ex) {
            // 4.3 执行业务报错,回滚事务
            completeTransactionAfterThrowing(txInfo, ex);
            throw ex;
        }
        finally {
            // 4.4 清理事务状态    
            cleanupTransactionInfo(txInfo);
        }
        // 4.5 业务执行成功,提交事务
        commitTransactionAfterReturning(txInfo);
        return retVal;
    }

    // 5.编程式事务(这个我们暂不分析,实际逻辑与声明式一致)
    else {
       ...
    }
    catch (ThrowableHolderException ex) {
        throw ex.getCause();
    }
}
}

通过上面的代码结构分析,我们可以大体看到事务执行的几个关键步骤

  1)getTransactionAttributeSource().getTransactionAttribute(method, targetClass)获取该方法的事务属性

//getTransactionAttributeSource()
public TransactionAttributeSource getTransactionAttributeSource() {
    return this.transactionAttributeSource;
}

 那么问题来了:transactionAttributeSource是什么时候被添加进来的呢?

不知道读者还记得我们在上篇博客中第三节SpringTransaction源码结构分析第4小结中分析AopAutoProxyconfigurer.configureAutoProxyCreator(element, parsercontext)时,以下代码段

// 2.注册类TransactionInterceptor到Spring中
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
interceptorDef.setSource(eleSource);
interceptorDef.setRole(BeanDefinition.ROLE_INFRAstructURE);
registerTransactionManager(element, interceptorDef);
// 看这里,在这里添加了transactionAttributeSource属性
// sourceName的值就是AnnotationTransactionAttributeSource类
interceptorDef.getPropertyValues().add("transactionAttributeSource", new runtimeBeanReference(sourceName));
String interceptorName = parserContext.getReaderContext().registerWithgeneratedName(interceptorDef);

  所以:getTransactionAttributeSource()返回的就是AnnotationTransactionAttributeSource类

继续看其getTransactionAttribute(method, targetClass),实现在AbstractFallbackTransactionAttributeSource类

// AbstractFallbackTransactionAttributeSource.getTransactionAttribute()
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
    if (method.getDeclaringClass() == Object.class) {
        return null;
    }

    // 1.查询缓存中是否存在
    Object cacheKey = getCacheKey(method, targetClass);
    Object cached = this.attributeCache.get(cacheKey);
    if (cached != null) {
        // Value will either be canonical value indicating there is no transaction attribute,
        // or an actual transaction attribute.
        if (cached == NULL_TRANSACTION_ATTRIBUTE) {
            return null;
        }
        else {
            return (TransactionAttribute) cached;
        }
    }
    else {
        // 2.获取方法上的事务配置属性
        TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
        // Put it in the cache.
        if (txAttr == null) {
            this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
        }
        else {
            String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
            if (txAttr instanceof DefaultTransactionAttribute) {
                ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
            }
            this.attributeCache.put(cacheKey, txAttr);
        }
        return txAttr;
    }
}

// computeTransactionAttribute(method, targetClass);
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
    // 1.注意这里,如果被代理方法非public类型,则直接返回空
    // 暂时不支持非public类型方法
    if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
        return null;
    }

    // ignore CGLIB subclasses - introspect the actual user class.
    Class<?> userClass = ClassUtils.getUserClass(targetClass);
    // The method may be on an interface, but we need attributes from the target class.
    // If the target class is null, the method will be unchanged.
    Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
    // If we are dealing with method with generic parameters, find the original method.
    specificMethod = BridgeMethodresolver.findBridgedMethod(specificMethod);

    // 2.解析方法上的@Transactional属性,具体解析过程读者可自行查看
    TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
    if (txAttr != null) {
        return txAttr;
    }

    // 3.如果方法上没有事务属性,就从类上来获取
    txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
    if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
        return txAttr;
    }

    if (specificMethod != method) {
        // Fallback is to look at the original method.
        txAttr = findTransactionAttribute(method);
        if (txAttr != null) {
            return txAttr;
        }
        // Last fallback is the class of the original method.
        txAttr = findTransactionAttribute(method.getDeclaringClass());
        if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
            return txAttr;
        }
    }

    return null;
}

  总结1):获取方法上的事务属性,如果方法上没有就从其类上来获取;

  注意:非public类型的方法直接返回空

  2)determineTransactionManager(txAttr);查找容器中的PlatformTransactionManager实现

protected PlatformTransactionManager determineTransactionManager(TransactionAttribute txAttr) {
    // Do not attempt to lookup tx manager if no tx attributes are set
    if (txAttr == null || this.beanFactory == null) {
        return getTransactionManager();
    }
    String qualifier = txAttr.getQualifier();
    if (StringUtils.hasText(qualifier)) {
        return determineQualifiedTransactionManager(qualifier);
    }
    else if (StringUtils.hasText(this.transactionManagerBeanName)) {
        return determineQualifiedTransactionManager(this.transactionManagerBeanName);
    }
    else {
        PlatformTransactionManager defaultTransactionManager = getTransactionManager();
        if (defaultTransactionManager == null) {
            defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
            if (defaultTransactionManager == null) {
                defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class);
                this.transactionManagerCache.putIfAbsent(
                    DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
            }
        }
        return defaultTransactionManager;
    }
}

主要功能就是从Spring容器中查找PlatformTransactionManager实现,由我们的示例可知,我们在在JdbcConfig中实现了该接口

@Bean
public DataSourceTransactionManager transactionManager(DataSource dataSource){
    return new DataSourceTransactionManager(dataSource);
}

  总结2):该方法返回我们自定义的DataSourceTransactionManager

  3)methodIdentification(method, targetClass, txAttr);获取被代理的类方法名称

private String methodIdentification(Method method, Class<?> targetClass, TransactionAttribute txAttr) {
    String methodIdentification = methodIdentification(method, targetClass);
    if (methodIdentification == null) {
        if (txAttr instanceof DefaultTransactionAttribute) {
            // 直接走这段代码,获取txAttr的description属性
            methodIdentification = ((DefaultTransactionAttribute) txAttr).getDescriptor();
        }
        if (methodIdentification == null) {
            methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
        }
    }
    return methodIdentification;
}

以上部分,我们获取了一些辅助信息,下面就开始分析最重要的部分了,声明式事务的操作

4.声明式事务的操作

// 4.1 创建TransactionInfo(重要操作在这里)
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.
    // 4.2 先执行其他Interceptor,执行完毕之后执行被代理类的方法
    retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
    // 4.3 执行业务报错,回滚事务
    completeTransactionAfterThrowing(txInfo, ex);
    throw ex;
}
finally {
    // 4.4 清理事务状态    
    cleanupTransactionInfo(txInfo);
}
// 4.5 业务执行成功,提交事务
commitTransactionAfterReturning(txInfo);
return retVal;

  1)createTransactionIfNecessary();创建TransactionInfo

这个几乎可以说是声明式事务中最重要的操作了,我们来好好看看这个方法

protected TransactionInfo createTransactionIfNecessary(
    PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {

    // If no name specified, APPly method identification as transaction name.
    if (txAttr != null && txAttr.getName() == null) {
        txAttr = new DelegatingTransactionAttribute(txAttr) {
            @Override
            public String getName() {
                return joinpointIdentification;
            }
        };
    }

    TransactionStatus status = null;
    if (txAttr != null) {
        if (tm != null) {
            // 1.主要方法,负责创建transaction
            status = tm.getTransaction(txAttr);
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
                             "] because no transaction manager has been configured");
            }
        }
    }
    // 2.封装TransactionInfo
    return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}

  * tm.getTransaction(txAttr);默认实现类为AbstractPlatformTransactionManager

public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
    // 1.获取当前线程事务
    // 本方法为抽象方法,具体实现,在本例中为DataSourceTransactionManager
    // 主要做法是从ThreadLocal中获取当前线程的Connection资源
    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();
    }

    // 2.如果当前线程已存在事务,则按照事务的传播机制来判断是否使用当前事务
    // 具体代码读者可进方法体细看,以加深对传播机制的了解
    if (isExistingTransaction(transaction)) {
        // Existing transaction found -> check propagation behavior to find out how to behave.
        return handleExistingTransaction(definition, transaction, debugEnabled);
    }

    // 3.查看事务是否已过时,过时则报错
    if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
        throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
    }

    // 4.能运行到这,说明当前线程不存在事务,那么与MANDATORY传播机制就不符合
    // MANDATORY要求当前线程必须存在事务,故直接抛出异常
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
        throw new IllegalTransactionStateException(
            "No existing transaction found for transaction marked with propagation 'mandatory'");
    }
    
    // 5.针对于requireD、requires_NEW、NESTED这三种传播机制
    // 当前线程之前不存在事务,则目前需要创建新的事务
    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);
            // 5.1 在这里创建新的Connection,本例中默认实现类为DataSourceTransactionManager
            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);
    }
}

通过以上代码结构的分析,我们可以大致看到获取Transaction的操作。

  主要过程就是:先从当前线程获取Transaction

      * 如果当前线程已有,则根据指定的传播机制,或重用,或新建Transaction;

      * 如果当前线程没有,则根据指定的传播机制,新建Transaction

下面我们再重点分析一下getTransaction()方法中的几个重要节点方法,

  分别是:

  handleExistingTransaction(definition, transaction, debugEnabled);

doBegin(transaction, definition);

 AbstractPlatformTransactionManager.handleExistingTransaction(definition, transaction, debugEnabled);

  当前线程已存在事务情况下创建事务分析

private TransactionStatus handleExistingTransaction(
    TransactionDefinition definition, Object transaction, boolean debugEnabled)
    throws TransactionException {

    // 1.如果隔离级别是NEVER,则说明不需要当前线程的已存在事务,则抛错
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
        throw new IllegalTransactionStateException(
            "Existing transaction found for transaction marked with propagation 'never'");
    }

    // 2.NOT_SUPPORTED,不需要Spring来创建事务
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
        if (debugEnabled) {
            logger.debug("Suspending current transaction");
        }
        Object suspendedResources = suspend(transaction);
        boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
        return prepareTransactionStatus(
            definition, null, false, newSynchronization, debugEnabled, suspendedResources);
    }

    // 3.REQUIRES_NEW,挂起当前事务,直接创建一个新的事务
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
        if (debugEnabled) {
            logger.debug("Suspending current transaction, creating new transaction with name [" +
                         definition.getName() + "]");
        }
        SuspendedResourcesHolder suspendedResources = suspend(transaction);
        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 beginEx) {
            resumeAfterBeginException(transaction, suspendedResources, beginEx);
            throw beginEx;
        }
        catch (Error beginErr) {
            resumeAfterBeginException(transaction, suspendedResources, beginErr);
            throw beginErr;
        }
    }

    // 4.NESTED ,创建当前事务的一个嵌套事务,嵌套事务独立于之前的线程事务进行提交或回滚
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
        if (!isNestedTransactionAllowed()) {
            throw new NestedTransactionNotSupportedException(
                "Transaction manager does not allow nested transactions by default - " +
                "specify 'nestedTransactionAllowed' property with value 'true'");
        }
        if (debugEnabled) {
            logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
        }
        if (useSavepointForNestedTransaction()) {
            // Create savepoint within existing Spring-managed transaction,
            // through the SavepointManager API implemented by TransactionStatus.
            // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
            DefaultTransactionStatus status =
                prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
            status.createAndHoldSavepoint();
            return status;
        }
        else {
            // Nested transaction through nested begin and commit/rollback calls.
            // Usually only for JTA: Spring synchronization might get activated here
            // in case of a pre-existing JTA transaction.
            boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
            DefaultTransactionStatus status = newTransactionStatus(
                definition, transaction, true, newSynchronization, debugEnabled, null);
            doBegin(transaction, definition);
            prepareSynchronization(status, definition);
            return status;
        }
    }

    // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
    if (debugEnabled) {
        logger.debug("Participating in existing transaction");
    }
    if (isValidateExistingTransaction()) {
        if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
            integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
            if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
                constants isoConstants = DefaultTransactionDefinition.constants;
                throw new IllegalTransactionStateException("Participating transaction with definition [" +
                                                           definition + "] specifies isolation level which is incompatible with existing transaction: " +
                                                           (currentIsolationLevel != null ?
                                                            isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
                                                            "(unknown)"));
            }
        }
        if (!definition.isReadOnly()) {
            if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
                throw new IllegalTransactionStateException("Participating transaction with definition [" +
                                                           definition + "] is not marked as read-only but existing transaction is");
            }
        }
    }
    boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
    return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}

 * doBegin(transaction, definition);创建一个Connection,本例中实现类为DataSourceTransactionManager

protected void doBegin(Object transaction, TransactionDefinition definition) {
    DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
    Connection con = null;

    try {
        // 1.如果当前线程没有相关Connection,则创建一个新的Connection
        if (txObject.getConnectionHolder() == null ||
            txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
            Connection newCon = this.dataSource.getConnection();
            if (logger.isDebugEnabled()) {
                logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
            }
            txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
        }

        txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
        con = txObject.getConnectionHolder().getConnection();

        // 2.设置隔离级别
        Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
        txObject.setPreviousIsolationLevel(previousIsolationLevel);

        // 3.在这里开启事务
        if (con.getAutoCommit()) {
            txObject.setMustRestoreAutoCommit(true);
            if (logger.isDebugEnabled()) {
                logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
            }
            // 重点在这里,是不是很熟悉,就是开启事务的标志
            con.setAutoCommit(false);
        }

        prepareTransactionalConnection(con, definition);
        txObject.getConnectionHolder().setTransactionActive(true);

        int timeout = determineTimeout(definition);
        if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
            txObject.getConnectionHolder().settimeoutInSeconds(timeout);
        }

        // Bind the connection holder to the thread.
        if (txObject.isNewConnectionHolder()) {
            TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
        }
    }

    catch (Throwable ex) {
        if (txObject.isNewConnectionHolder()) {
            DataSourceUtils.releaseConnection(con, this.dataSource);
            txObject.setConnectionHolder(null, false);
        }
        throw new cannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
    }
}

  总结1):在createTransactionIfNecessary()方法里,

  我们会获取当前线程的事务,如果已经存在则按照相应的传播机制或使用已有事务或创建新的事务;

  如果不存在事务,则根据传播机制,或创建新的事务或不创建;

  将事务信息包装到TransactionInfo中,TransactionInfo用于后面的事务提交及回滚

  2)invocation.proceedWithInvocation();;执行业务操作

// 直接走回调方法
public Object invoke(final MethodInvocation invocation) throws Throwable {
    ...
    return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
        @Override
        public Object proceedWithInvocation() throws Throwable {
            // 也就是该方法,实现类为ReflectiveMethodInvocation
            return invocation.proceed();
        }
    });
}

// ReflectiveMethodInvocation.proceed()
public Object proceed() throws Throwable {
    //	1.业务方法调用
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        // invokeJoinpoint()方法内容为
        // AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
        // 即真正调用业务实现,也就是本例中的save()方法
        return invokeJoinpoint();
    }

    // 2.如果还有其他intercept,则先调用
    Object interceptorOrInterceptionAdvice =
        this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
        // Evaluate dynamic method matcher here: static part will already have
        // been evaluated and found to match.
        InterceptorAndDynamicMethodMatcher dm =
            (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
        if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
            return dm.interceptor.invoke(this);
        }
        else {
            // Dynamic matching failed.
            // Skip this interceptor and invoke the next in the chain.
            return proceed();
        }
    }
    else {
        // It's an interceptor, so we just invoke it: The pointcut will have
        // been evaluated statically before this object was constructed.
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

 3)completeTransactionAfterThrowing(txInfo, ex);业务执行报错,执行事务回滚

// Transactionaspectsupport.completeTransactionAfterThrowing()
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);
        }
        // 判断回滚的默认依据是 抛出的异常是否是RuntimeException或者ERROR类型
        if (txInfo.transactionAttribute.rollbackOn(ex)) {
            try {
                // 重要方法,真正进行事务回滚的方法
                txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
            }
            ...
        }
        // 如果不是,则提交事务
        else {
            // We don't roll back on this exception.
            // Will still roll back if TransactionStatus.isRollbackOnly() is true.
            try {
                txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
            }
           ...
        }
    }
}

//  txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());事务回滚
// 默认实现在AbstractPlatformTransactionManager
public final void rollback(TransactionStatus status) throws TransactionException {
    // 1.如果是已完成状态,则直接抛错
    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);// 回滚处理
}

// processRollback(defStatus)
private void processRollback(DefaultTransactionStatus status) {
    try {
        try {
            ...
            // 我们直接看新创建的事务如何进行回滚的
            else if (status.isNewTransaction()) {
                if (status.isDebug()) {
                    logger.debug("Initiating transaction rollback");
                }
                // 重要实现,默认在DataSourceTransactionManager实现
                doRollback(status);
            }
           ...
        }
       ...
    }
    finally {
        cleanupAfterCompletion(status);
    }
}

// DataSourceTransactionManager.doRollback(status);回滚
protected void doRollback(DefaultTransactionStatus status) {
    DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
    Connection con = txObject.getConnectionHolder().getConnection();
    if (status.isDebug()) {
        logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
    }
    try {
        // 看到这里读者是不是很熟悉了,就是我们的connection.rollback()方法
        con.rollback();
    }
    catch (SQLException ex) {
        throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
    }
}

  总结3):回滚事务,根据不同的情况有不同的处理方案,具体细节不再赘述;

  针对于新创建的事务,最终还是调用Connection.rollback()方法来实现

  4)commitTransactionAfterReturning(txInfo);事务提交

// TransactionAspectSupport.commitTransactionAfterReturning()
protected void commitTransactionAfterReturning(TransactionInfo txInfo) {
    if (txInfo != null && txInfo.hasTransaction()) {
        if (logger.isTraceEnabled()) {
            logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
        }
        // 重点在这里
        txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
    }
}

//AbstractPlatformTransactionManager.commit()
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()) {
        if (defStatus.isDebug()) {
            logger.debug("Transactional code has requested rollback");
        }
        processRollback(defStatus);
        return;
    }
    if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
        if (defStatus.isDebug()) {
            logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
        }
        processRollback(defStatus);
        // Throw unexpectedRollbackException only at outermost transaction boundary
        // or if explicitly asked to.
        if (status.isNewTransaction() || isFailearlyOnGlobalRollbackOnly()) {
            throw new UnexpectedRollbackException(
                "Transaction rolled back because it has been marked as rollback-only");
        }
        return;
    }

    // 真正的事务提交逻辑
    processCommit(defStatus);
}

// AbstractPlatformTransactionManager.processCommit()
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
    try {
        boolean beforeCompletionInvoked = false;
        try {
            prepareForCommit(status);
            triggerBeforeCommit(status);
            triggerBeforeCompletion(status);
            beforeCompletionInvoked = true;
            boolean globalRollbackOnly = false;
            ...
            // 我们直接看新事务的提交
            else if (status.isNewTransaction()) {
                if (status.isDebug()) {
                    logger.debug("Initiating transaction commit");
                }
                // 抽象方法,默认由DataSourceTransactionManager实现
                doCommit(status);
            }
            // Throw UnexpectedRollbackException if we have a global rollback-only
            // marker but still didn't get a corresponding exception from commit.
            if (globalRollbackOnly) {
                throw new UnexpectedRollbackException(
                    "Transaction silently rolled back because it has been marked as rollback-only");
            }
        }
        ...
    }
    finally {
        cleanupAfterCompletion(status);
    }
}

//DataSourceTransactionManager.doCommit()
protected void doCommit(DefaultTransactionStatus status) {
    DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
    Connection con = txObject.getConnectionHolder().getConnection();
    if (status.isDebug()) {
        logger.debug("Committing JDBC transaction on Connection [" + con + "]");
    }
    try {
        // 还是这里,熟悉的味道
        con.commit();
    }
    catch (SQLException ex) {
        throw new TransactionSystemException("Could not commit JDBC transaction", ex);
    }
}

总结:通过上面一系列的代码分析,我们可以看到,事务的开启、提交、回滚也都是按照传统的事务方式来的。

只是事务的获取需要根据事务传播机制来获取。

相关阅读

APP流量变现:互动试玩广告流量变现的全过程解析

在移动互联网时代一向崇尚&ldquo;流量为王&rdquo;,可对APP开发者来说即使在拥有相同流量的情况下,因选广告不同,变现效果也可能天差

贪吃蛇大作战JavaFx版完整源码

贪吃蛇大作战 Java版项目源码:https://github.com/silence1772/JavaFX-GreedySnake(记得点star啊,收藏一个项目最好的方式是star而

CoordinatorLayout使用全解析

转载自 伯努力不努力 的博客 https://blog.csdn.net/u012124438/article/details/56701641 C

“ora-12154无法解析指定的连接标识符”问题解决

环境:win10, oracle10.2.1, plsql 7.4问题:安装完oracle后,使用plsql连接数据库,发现总是报“ora-12154无法解析指定的连接标识符”错

RTF 文件格式解析

##RTF 格式解析例子内容代码如下{\rtf1\ansi\ansicpg936\deff0\deflang1033\deflangfe2052{\fonttbl{\f0\fnil\fcharse

分享到:

栏目导航

推荐阅读

热门阅读