当前位置 : 主页 > 编程语言 > java >

【老王读Spring Transaction-4】Spring事务管理的核心原理——PlatformTransactionManager&

来源:互联网 收集:自由互联 发布时间:2022-08-15
@TOC 前言 通过编程的方式实现一个事务管理的过程可以分为三步: begin: 获取连接 commit: 提交事务(业务正常执行) rollback: 回滚事务(业务异常) Spring 中通过 @Transactional 注解的方式实

@TOC

前言

通过编程的方式实现一个事务管理的过程可以分为三步:

  • begin: 获取连接
  • commit: 提交事务(业务正常执行)
  • rollback: 回滚事务(业务异常)
  • Spring 中通过 @Transactional 注解的方式实现了切面式的事务管理,其本质还是会经历上面三个步骤。

    下面我们就来研究一下 Spring 中是怎么实现事务的管理的。

    Spring 版本

    spring-tx 5.3.9 (通过 SpringBoot 2.5.3 间接引入的依赖)

    正文

    Spring 中通过 PlatformTransactionManager 来实现事务的管理。 TransactionManager.png

    PlatformTransactionManager

    PlatformTransactionManager 是 Spring 事务实现的核心接口。通常,我们会通过 @Transactional 的方式 或者 TransactionTemplate 编程式的方式来使用 PlatformTransactionManager。

    @Transactional 底层是通过 AOP 的方式来使用 PlatformTransactionManager 的

    PlatformTransactionManager 提供了三个方法用来管理事务:

  • getTransaction(TransactionDefinition)
  • commit(TransactionStatus)
  • rollback(TransactionStatus)
  • PlatformTransactionManager 的源码如下:

    public interface PlatformTransactionManager extends TransactionManager { /** * 根据指定的事务传播行为,返回当前活动的事务或创建新事务。 * 注意: 隔离级别 或 timeout 等参数只会应用到新开启的事务上,因此,如果是加入到当前活动事务时,这些参数将会被忽略。 * @param TransactionDefinition 用于描述 事务传播行为、隔离级别、timeout 等 * @return TransactionStatus 表示当前事务 * @see TransactionDefinition#getPropagationBehavior * @see TransactionDefinition#getIsolationLevel * @see TransactionDefinition#getTimeout */ TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException; /** * 提交给定的 TransactionStatus。 * 如果事务已通过编程方式标记为 rollback-only,将会执行回滚。 * 如果事务不是一个新开启的事务,则忽略本次提交操作(因为事务可能嵌套,嵌套在内部的事务在执行 commit 操作时,是不需要真正执行 commit 的)。 * @param getTransaction() 方法返回的 TransactionStatus 对象 */ void commit(TransactionStatus status) throws TransactionException; /** * 回滚给定的 TransactionStatus。 * 如果事务不是新开启的事务,则只将事务标记为 rollback-only。 * @param getTransaction() 方法返回的 TransactionStatus 对象 */ void rollback(TransactionStatus status) throws TransactionException; }

    PlatformTransactionManager#commit() 方法会被 TransactionAspectSupport#commitTransactionAfterReturning() 调用,这样就和 Spring AOP 衔接起来了。

    PlatformTransactionManager 接口主要是通过 AbstractPlatformTransactionManager 来实现的。 AbstractPlatformTransactionManager 是实现 Spring 标准事务工作流的抽象基类,它是 DataSourceTransactionManager、JtaTransactionManager 等具体的平台事务管理器的基础。

    TransactionStatus

    TransactionStatus接口

    TransactionStatus 能够获取事务的状态信息,它为事务代码提供了一种控制事务执行和查询事务状态的简单方法。 比如:它可以获取到当前是否是一个新开启的事务、事务有没有完成 等

    public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable { @Override boolean isNewTransaction(); boolean hasSavepoint(); // 这里可以控制事务执行的行为。其他方法都是获取事务的状态信息。 @Override void setRollbackOnly(); @Override boolean isRollbackOnly(); void flush(); @Override boolean isCompleted(); }

    TransactionStatus.png

    DefaultTransactionStatus

    DefaultTransactionStatus 是 TransactionStatus 接口的默认实现。它由 PlatformTransactionManager 使用,保存了 AbstractPlatformTransactionManager 内部需要的所有状态信息。

    DefaultTransactionStatus.png

    DefaultTransactionStatus 的构造函数如下:

    public DefaultTransactionStatus( @Nullable Object transaction, boolean newTransaction, boolean newSynchronization, boolean readOnly, boolean debug, @Nullable Object suspendedResources) { this.transaction = transaction; // 当前事务对象(可为 null) this.newTransaction = newTransaction; // 是否需要新开启一个事务 this.newSynchronization = newSynchronization; // 是否需要开启新的事务同步 this.readOnly = readOnly; // 是否只读 this.debug = debug; this.suspendedResources = suspendedResources; // 当前挂起的事务(可为 null) }

    Spring 在每进入一个 @Transactional 方法时,都会创建一个 TransactionStatus 对象: DefaultTransactionStatus,用于记录本次事务的状态信息。 TransactionStatus 可以代表新事务,也可以代表现有的事务。

    TransactionStatus 与 PlatformTransactionManager 结合使用

    TransactionStatus 可以获取事务的状态信息,但是它并不负责事务的管理(提交 or 回滚)。 Spring 是通过 PlatformTransactionManager 来实现事务的管理的,其中提交 或 回滚事务都是以 TransactionStatus 做为入参的。

    PlatformTransactionManager.png

    PlatformTransactionManager 管理事务的两种使用方式

    PlatformTransactionManager 提供了事务管理的能力,而 Spring 提供了两种方式来调用 PlatformTransactionManager 来实现事务管理:一是,@Transactional 注解的方式;二是,TransactionTemplate 编程的方式。

    TransactionTemplate 编程的方式

    使用 TransactionTemplate 编程的方式来使用事务的话,可以使用类似如下的代码:

    transactionTemplate.execute(new TransactionCallbackWithoutResult(){ protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) { String sql = "insert into t_stu(id,name) values(?,?)"; jdbcTemplate.update(sql,1,"张三"); } });

    很显然,这样方式是使用了模板方法的模式,让 TransactionTemplate 去执行具体的事务管理操作,用户只需要填充业务代码就可以了。

    TransactionTemplate#execute() 的源码如下:

    // TransactionTemplate#execute() public <T> T execute(TransactionCallback<T> action) throws TransactionException { if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) { return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action); } else { TransactionStatus status = this.transactionManager.getTransaction(this); T result; try { // 在事务中执行业务操作 result = action.doInTransaction(status); } catch (RuntimeException | Error ex) { // 判断是否要对 RuntimeException 和 Error 进行回滚 rollbackOnException(status, ex); throw ex; } catch (Throwable ex) { // 判断是否要对 Throwable 进行回滚 rollbackOnException(status, ex); throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception"); } // 业务操作正常结束,则执行 commit 操作 this.transactionManager.commit(status); return result; } }

    可以看到,处理流程如下:

  • 通过 PlatformTransactionManager 获取到 TransactionStatus
  • 在事务中执行业务方法
  • 业务方法正常结束,则通过 PlatformTransactionManager 对 TransactionStatus 执行 commit
  • 业务方法异常结束,则通过 PlatformTransactionManager 对 TransactionStatus 执行 rollback
  • TransactionTemplate 编程的方式来管理事务,在实际的开发中比较少用到。推荐使用的是 @Transactional 注解的方式来自动管理事务

    @Transactional 注解的方式

    @Transactional 的方式来自动管理事务,底层是通过 Spring AOP 来实现的。

    前面在分析 @Transactional 的实现原理时 讲到:Spring 是通过 TransactionInterceptor 来自动实现事务拦截的。 TransactionInterceptor 会调用父类的 TransactionAspectSupport#invokeWithinTransaction() 方法来执行事务方法,代码如下: TransactionAspectSupport.png

    可以看到,@Transactional 的处理流程如下:

  • 创建 TransactionInfo 对象,包含: TransactionStatus、PlatformTransactionManager 等信息
  • 执行业务方法
  • 业务方法正常结束,则执行 commit
  • 业务方法异常结束,则执行 rollback
  • @Transactional 的处理流程和 TransactionTemplate#execute() 的流程是类似的。

    TransactionAspectSupport 中关于事务的操作,都是通过 PlatformTransactionManager 来进行的,比如:TransactionAspectSupport#commitTransactionAfterReturning() 会调用 PlatformTransactionManager#commit() 方法。 这样 Spring AOP 就与 PlatformTransactionManager 衔接起来了。

    小结

    PlatformTransactionManager 是 Spring 事务实现的核心接口,它和 TransactionStatus 共同来完成事务的管理。 TransactionStatus 主要是用来获取事务的状态信息,而 PlatformTransactionManager 是基于事务状态信息来提交 或 回滚事务。

    PlatformTransactionManager 提供了三个方法用来管理事务:

  • getTransaction(TransactionDefinition)
  • commit(TransactionStatus)
  • rollback(TransactionStatus)
  • Spring 对事务的管理流程如下:

  • 通过 PlatformTransactionManager 获取到 TransactionStatus
  • 在事务中执行业务方法
  • 业务方法正常结束,则通过 PlatformTransactionManager 对 TransactionStatus 执行 commit
  • 业务方法异常结束,则通过 PlatformTransactionManager 对 TransactionStatus 执行 rollback
  • 上一篇:hive -f -e 替换\t为逗号
    下一篇:没有了
    网友评论