暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

03.Spring事务的源码(二):事务执行的流程(开启,回滚,提交)

阿亮的日志 2021-04-14
876

导读

从事务的基础知识到一些核心源码的分析,然后逐步引入到分布式事务的常用解决方案,以及分布式事务核心框架源码的讲解。

(本系列持续更新,感兴趣请关注我的公众号,不错过下一波干货)。

前言

上面一篇已经完成了源码的入门,我们已经知道了核心流程的处理类,本篇开始,我们会逐步完善上一篇中的图。这一篇从事务的开启,到业务逻辑执行,已经事务提交或者回滚的流程进行,梳理完成整个spring事务流程的处理。

知识点

  • 事务开启的源码
  • 业务逻辑执行
  • 事务的提交与回滚

1.主流程回顾

从上篇文章中我们已经知道执行核心业务逻辑的代码如下(隐藏了非核心业务代码):

protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)throws Throwable {
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
    // 事务的开启
 TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
 Object retVal = null;
 try {
    // 执行业务逻辑
  retVal = invocation.proceedWithInvocation();
 }
 catch (Throwable ex) {
     //事务回滚
  completeTransactionAfterThrowing(txInfo, ex);
  throw ex;
 }
 finally {
  cleanupTransactionInfo(txInfo);
 }
 //事务提交
 commitTransactionAfterReturning(txInfo);
 return retVal;
}
     
 }

主要包含4个核心流程

  • 事务的开启:createTransactionIfNecessary
  • 执行业务逻辑:invocation.proceedWithInvocation()
  • 事务的回滚:completeTransactionAfterThrowing(txInfo, ex);
  • 事务的提交:commitTransactionAfterReturning(txInfo);

2.事务处理的核心流程

2.1.事务的开启

我们从上一篇TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification)
作为入口,进行代码的跟踪

 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) {
       //改行代码为核心的开启事务方法,这里的tm是`PlatformTransactionManager`,实际的逻辑是由`AbstractPlatformTransactionManager`来实现的
    status = tm.getTransaction(txAttr);
   }
   else {
    if (logger.isDebugEnabled()) {
     logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
       "] because no transaction manager has been configured");
    }
   }
  }
  return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
 }

  • 这里的tm
    PlatformTransactionManager
    ,事务管理器,核心逻辑由其父类AbstractPlatformTransactionManager
    来处理
  • 事务的开启经过TransactionManager
    最终还是会调用底层的JDBC
    来开启事务,通过beginTransaction()
    方法实现

2.2.业务逻辑的执行

核心业务逻辑是通过代理模式去执行invocation.proceedWithInvocation()

  • 如果执行逻辑中出现异常,则走catch流程,调用completeTransactionAfterThrowing
    进行事务的回滚,执行完成后抛出异常,中断,不再走下面的逻辑
  • 如执行成功,则commitTransactionAfterReturning
    进行事务的提交

2.3.事务的回滚

若上述业务逻辑执行失败,则回执行catch中的事务回滚代码completeTransactionAfterThrowing
,并中断下面代码的执行。这一块不再贴代码

我们可以看到整体的流程和开启事务流程基本一致:

  • 都是通过TM
    来处理,经过几个核心组件的调用之后,最终都是通过JDBC
    来完成事务的回滚。

2.4.事务的提交

若第二步业务逻辑执行成功,则执行事务提交的代码commitTransactionAfterReturning

我们可以看到整体的流程和事务的回滚流程基本一致:

  • 都是通过TM
    来处理,经过几个核心组件的调用之后,最终都是通过JDBC
    来完成事务的提交。

3.Spring事务的设计

我们看到上面的核心流程涉及到了如下几个类,那么我们来研究下这些类有哪些用途。

3.1.核心类

3.1.1.PlatformTransactionManager

public interface PlatformTransactionManager {

 TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

 void commit(TransactionStatus status) throws TransactionException;

 void rollback(TransactionStatus status) throws TransactionException;

}


这里涉及到3个最核心的方法,而我们使用的是该接口的抽象类AbstractPlatformTransactionManager

3.1.2.TransactionDefinition

该类定义了事务的一些属性和定义,其中事务的隔离级别就在该类中实现,上面开启事务的实现需要依赖该类作为参数

3.2.设计思路

spring事务是通过代理模式,在流程中通过TransactionInterceptor
对业务逻辑进行增强实现,其实就是通过Aop的思想来实现。这个在很多的框架中都是这么实现的,这种设计对于代码的侵入性较低。后续我们研究分布式事务组件TCC的时候也会看的这样的使用方式。

关于

更多内容可关注公众号

  • Github: https://github.com/liangliang1259/common-notes
  • 公众号


文章转载自阿亮的日志,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论