美文网首页
Transaction 事务

Transaction 事务

作者: 你弄啥来 | 来源:发表于2019-09-25 23:22 被阅读0次

一、官网地址:
https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/data-access.html#
Transaction
二、实现方式:
2.1 通过xml配置:
2.1.1配置transanctionManager, 属性 dataSource

<bean id="txManager" 
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
      <property name="dataSource" ref="dataSource"/> 
</bean>

2.1.2 基于Aop 配置事务增强 <tx> 标签 是transaction 提供的标签,在这里可以配置指定某些方法定义事务的传播行为,隔离级别。


image.png

2.2 通过注解配置:
开启spring 注解事务的注解:@EnableTransactionManagement
在要加事务管理的类或方法上加@Transactional,如果需要对事务的其他属性进行配置时,即在注解上面配置相关属性即可。


image.png

2.3 编程式事务:
1 定义TransactionDefinition 作为transactionManager的入参条件来获取TransactionStatus,其中DefaultTransactionDefinition 定义了事务的属性。

        TransactionDefinition definition = new DefaultTransactionDefinition(); 
        TransactionStatus status = txManager.getTransaction(definition);
      try{
            //业务
          txManager.commit(status);
        }catch(Exception e){
            //出现异常手动回滚
            txManager.rollback(status );
        }
还有一种直接获取TransactionStatus 并将他设置成rollbackOnly
public void resolvePosition() {
    try {
        // some business logic...
    } catch (NoProductInStockException ex) {
        // trigger rollback programmatically
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
}

2 spring 还提供了事务模版用来管理事务:
TransactionTemplate 执行 execute();方法来完成相关事务操作。
可以自己在此基础上造个轮子:

package com.chen.springboot.bootlearn.template;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

@Component
public class SpringTransaction {

    @Autowired
    private TransactionTemplate transactionTemplate;  // TransactionTemplate 作为spring bean维护
    
    //提供一个模版方法 子类重写具体业务
    public Object execute(TransactionTemplates templates) {
        Object result = new Object();
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                try {
                    templates.lock();
                } finally {
                    System.out.println("Lock");
                }
                try {
                    templates.check();
                } finally {
                    System.out.println("Check");
                }
                try {
                    templates.process();
                } finally {
                    System.out.println("Process");
                }
            }
        });
        return result;
    }
}

遇到需要调用事务的时候 直接执行 execute()方法即可

    @Override
    public Object addCount(User user) {
        Object object = new Object();
        transaction.execute(new TransactionTemplates() {
            @Override
            public void check() {
            }
            @Override
            public void lock() {
            }
            @Override
            public void process() {
            }
        });
        return object;
    }

三 事务API
Spring事务核心的API:
3.1 : PlatformTransactionManager,平台级的事务管理器,它抽象定义了事务管理行为,不同
的事务管理实现实现该接口。我们编程面向该接口。继承关系图如下所示:


image.png

3.1.1 抽象方法也很简单:


image.png

3.2 : TransactionDefinition:事务定义。Spring 事务管理框架将为我们管理事务,但不清楚该
如何替我们管理,我们就通过事务定义来定义我们需要的事务管理信息,把这些信息给事务
管理器,它就知道我们的意图了。
接口 的结构图如下所示:


image.png

继承关系图:


image.png

3.3:TransactionStatus 事务状态,持有事务的状态信息。事务管理代码可通过它获取事务状态、
以及显式地设置回滚(代替异常的方式)。它继承了 SavePoint 接口。在它的实现中会持有事
务的很多对象:如事务对象、被挂起的事务资源等。
从 TransactionManager 中获取事务得到它,提交/回滚事务时要给入它:
类结构图:


image.png

继承关系图:


image.png

四 具体实现流程:
验证:DataSourceTransactionManager
DataSourceTransactionManager 是基于 jdbc connection 的本地事务管理实现。多个方法
调用参与到同一个事务,是通过共用 connection 来完成的。
通过不同的事务传播属性,执行方法时也会有不同。验证不同传播属性对事务的影响:
方法一 required --- 方法二 required
方法一 required --- 方法二 requires_new
方法一 required --- 方法二 nested (当前存在事务 则嵌套在事务内执行,没有事务则新开启一个事务)
具体代码 主要集中在 AbstractPlatformTransactionManager

典型的模板方法的设计模式, 子类调用父类的 getTransaction(),这个方法时不能不能不重写的方法,子类只能重写里面的 doGetTransaction() 封装事务对象,isExistingTransaction():判断是否存在事务,handleExistingTransaction():存在事务的处理流程,doBegin():开启事务。doCommit():提交事务,doRollback():回滚事务。


image.png
        @Override
    public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
                //获取事务对象 TransactionObject 由子类去实现
        Object transaction = doGetTransaction();

        if (definition == null) {
            // Use defaults if no transaction definition given.
            definition = new DefaultTransactionDefinition();
        }
      if (isExistingTransaction(transaction)) {//是否存在事务
            //存在事务如何处理
            return handleExistingTransaction(definition, transaction, debugEnabled);
        }
    
        // 不存在事务检查事务传播行为
        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);
            try {

//封装: DefaultTransactionStatus : 1事务对象 2是否是新事务 3 事务同步器是否开启默认是开着的 4 是否 开启只读控制。 5 挂起的资源  
                DefaultTransactionStatus status = newTransactionStatus(
                        definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
                                //开启事务
                doBegin(transaction, definition);
                prepareSynchronization(status, definition);
                return status;
            }
            catch (RuntimeException | Error ex) {
                resume(null, suspendedResources);
                throw ex;
            }
        }
        else {
            // 传播行为 为其他的时候就不做任何处理,也要封装一个 TransactionStatus对象
            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);
        }
    }

具体执行流程如下图所示:

SptingTransation.png

获取事务对象:

    @Override
    protected Object doGetTransaction() {
                // 每来一个事务时都要创建一个事务对象
        DataSourceTransactionObject txObject = new DataSourceTransactionObject();
        txObject.setSavepointAllowed(isNestedTransactionAllowed());
        ConnectionHolder conHolder =
              //从当前ThreadLocal (TransactionSynchronizationManager) 中获取一个连接 并放到事务对象。
                (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
        txObject.setConnectionHolder(conHolder, false);
        return txObject;
    }

TransactionSynchronizationManager 为了保证多线程下事务不出现混乱,通过ThreadLocal 来保证线程的同步.

public abstract class TransactionSynchronizationManager {

    private static final Log logger = LogFactory.getLog(TransactionSynchronizationManager.class);

    private static final ThreadLocal<Map<Object, Object>> resources =
            new NamedThreadLocal<>("Transactional resources");

    private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
            new NamedThreadLocal<>("Transaction synchronizations");

    private static final ThreadLocal<String> currentTransactionName =
            new NamedThreadLocal<>("Current transaction name");

    private static final ThreadLocal<Boolean> currentTransactionReadOnly =
            new NamedThreadLocal<>("Current transaction read-only status");

    private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
            new NamedThreadLocal<>("Current transaction isolation level");

    private static final ThreadLocal<Boolean> actualTransactionActive =
            new NamedThreadLocal<>("Actual transaction active");

                                                  ···················
}

判断是否存在事务:

    @Override
    protected boolean isExistingTransaction(Object transaction) {
//判断事务对象中是否存在连接持有器,连接持有器中的事务是否被激活
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
        return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
    }

对挂起事务的恢复

    protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
            throws TransactionException {

        if (resourcesHolder != null) {
            Object suspendedResources = resourcesHolder.suspendedResources;
            if (suspendedResources != null) {
                doResume(transaction, suspendedResources);
            }
            List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
            if (suspendedSynchronizations != null) {
                TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);
                TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);
                TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);
                TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);
                doResumeSynchronization(suspendedSynchronizations);
            }
        }
    }

相关文章

网友评论

      本文标题:Transaction 事务

      本文链接:https://www.haomeiwen.com/subject/toeuuctx.html