Spring 事务原理总结三

今天这篇文章,我想梳理一下Spring事务用到的几个核心组件。这些核心组件是我们理解Spring事务原理的基础。通过它们我们可以体会学习一下Spring设计者设计Spring事务时的基本思路。这些组件是:TransactionInfo、TransactionStatus、TransactionManager、TransactionAttribute、TransactionAttributeSource、ReactiveTransactionSupport等等。

首先让我们一起看一下TransactionInfo类。它是一个位于TransactionAspectSupport类中的内部类(这个类是上一节介绍的TransactionInterceptor的父类,TransactionInterceptor是一个增强类,用于对那些需要事务的方法进行增强。可以这样讲TransactionInterceptor类是Spring事务处理的核心拦截器,它会根据方法的事务属性,在目标方法调用前后进行必要的事务边界管理(开启、提交或回滚事务))。TransactionInfo类的源码如下:

protected static final class TransactionInfo {
    @Nullable
    private final PlatformTransactionManager transactionManager;
    @Nullable
    private final TransactionAttribute transactionAttribute;
    private final String joinpointIdentification;
    @Nullable
    private TransactionStatus transactionStatus;
    @Nullable
    private TransactionInfo oldTransactionInfo;
    public TransactionInfo(@Nullable PlatformTransactionManager transactionManager,
          @Nullable TransactionAttribute transactionAttribute, String joinpointIdentification) {
       this.transactionManager = transactionManager;
       this.transactionAttribute = transactionAttribute;
       this.joinpointIdentification = joinpointIdentification;
    }
    public PlatformTransactionManager getTransactionManager() {
       Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");
       return this.transactionManager;
    }
    @Nullable
    public TransactionAttribute getTransactionAttribute() {
       return this.transactionAttribute;
    }
    /**
     * Return a String representation of this joinpoint (usually a Method call)
     * for use in logging.
     */
    public String getJoinpointIdentification() {
       return this.joinpointIdentification;
    }
    public void newTransactionStatus(@Nullable TransactionStatus status) {
       this.transactionStatus = status;
    }
    @Nullable
    public TransactionStatus getTransactionStatus() {
       return this.transactionStatus;
    }
    /**
     * Return whether a transaction was created by this aspect,
     * or whether we just have a placeholder to keep ThreadLocal stack integrity.
     */
    public boolean hasTransaction() {
       return (this.transactionStatus != null);
    }
    private void bindToThread() {
       // Expose current TransactionStatus, preserving any existing TransactionStatus
       // for restoration after this transaction is complete.
       this.oldTransactionInfo = transactionInfoHolder.get();
       transactionInfoHolder.set(this);
    }
    private void restoreThreadLocalStatus() {
       // Use stack to restore old transaction TransactionInfo.
       // Will be null if none was set.
       transactionInfoHolder.set(this.oldTransactionInfo);
    }
    @Override
    public String toString() {
       return (this.transactionAttribute != null ? this.transactionAttribute.toString() : "No transaction");
    }
}

通过源码不难看出TransactionInfo是一个最终类,也没有继承或实现其他接口或类,其中的属性有PlatformTransactionManager、TransactionAttribute、TransactionStatus、TransactionInfo(通过其变量名可以知道其代表的是老事务。还记得《Spring事务原理总结一》这篇文章中提到的事务传播属性吗?其中提到的REQUIRES_NEW可能就是通过这个属性来实现的)等。那这个类的作用究竟是什么呢?个人理解它是一个上下文数据结构,用于存储事务定义(TransactionDefinition。事务定义是通过TransactionInfo类中的TransactionAttribute属性完成的,这个类继承了TransactionDefinition接口)、事务状态(TransactionStatus)以及事务同步器列表等关键数据。说白了其存在的目的就是维护事务运行期间所需的必要信息

然后让我们再一起看一下TransactionStatus接口,其又继承了SavepointManager、Flushable、TransactionExecution等接口。下面是该接口的源码:

public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {

    /**
     * Return whether this transaction internally carries a savepoint,
     * that is, has been created as nested transaction based on a savepoint.
     * <p>This method is mainly here for diagnostic purposes, alongside
     * {@link #isNewTransaction()}. For programmatic handling of custom
     * savepoints, use the operations provided by {@link SavepointManager}.
     * <p>The default implementation returns {@code false}.
     * @see #isNewTransaction()
     * @see #createSavepoint()
     * @see #rollbackToSavepoint(Object)
     * @see #releaseSavepoint(Object)
     */
    default boolean hasSavepoint() {
       return false;
    }

    /**
     * Flush the underlying session to the datastore, if applicable:
     * for example, all affected Hibernate/JPA sessions.
     * <p>This is effectively just a hint and may be a no-op if the underlying
     * transaction manager does not have a flush concept. A flush signal may
     * get applied to the primary resource or to transaction synchronizations,
     * depending on the underlying resource.
     * <p>The default implementation is empty, considering flush as a no-op.
     */
    @Override
    default void flush() {
    }

}

下图则是TransactionStatus接口的继承体系:

看到这里我不禁在想,这个类究竟是干什么的。在Spring框架中,TransactionStatus是用于表示事务运行时状态的接口。在Spring事务管理模块中,当开始一个新的事务或参与到一个现有事务时,会返回一个实现了TransactionStatus接口的对象实例。这个接口会提供以下几个功能:

  1. 设置保存点(setSavepoint):在事务执行过程中创建一个保存点,可以在后续需要时回滚到该保存点
  2. 回滚到保存点(rollbackToSavepoint):根据给定的保存点回滚事务的部分操作
  3. 确定是否是新创建的事务(isNewTransaction):判断当前事务是否是一个新的、尚未提交的事务
  4. 完成事务(commit)和回滚事务(rollback):分别用来提交当前事务的所有更改或者撤销所有更改并恢复到事务开始前的状态
  5. 标记事务为只读(setReadOnly):对于某些数据库,可以利用此方法优化事务处理性能,通过设定事务为只读后,数据库可能会采取一些特殊的优化策略
  6. 获取事务是否处于只读模式(isReadOnly):查询当前事务是否被标记为只读
  7. 确定事务是否已经完成(isCompleted):检查事务是否已经被提交或回滚,即事务生命周期是否结束

总之,通过这个接口,开发者可以在程序运行时对事务进行细粒度的控制,以满足复杂的业务场景需求。在Spring声明式事务管理中,这些操作通常由Spring框架自动完成,但在编程式事务管理场景下,开发者可以直接操作TransactionStatus对象来手动控制事务的边界和行为

接着来让我们来看一下TransactionAttribute接口,该位于org.springframework.transaction.interceptor包中,先来看一下其源码:

public interface TransactionAttribute extends TransactionDefinition {

    /**
     * Return a qualifier value associated with this transaction attribute.
     * <p>This may be used for choosing a corresponding transaction manager
     * to process this specific transaction.
     * @since 3.0
     */
    @Nullable
    String getQualifier();

    /**
     * Return labels associated with this transaction attribute.
     * <p>This may be used for applying specific transactional behavior
     * or follow a purely descriptive nature.
     * @since 5.3
     */
    Collection<String> getLabels();

    /**
     * Should we roll back on the given exception?
     * @param ex the exception to evaluate
     * @return whether to perform a rollback or not
     */
    boolean rollbackOn(Throwable ex);

}

下图是TransactionAttribute这个接口的继承体系(这里面重点关注RuleBasedTransactionAttribute这个类,第一次跟踪事务的执行代码时实际类型为RuleBasedTransactionAttribute):

跟TransactionStatus接口类似,我对TransactionAttribute接口的作用也非常好奇,通过不懈的查找,我找到了以下一些资料:

在Spring中,通过注解(@Transactional)或在配置文件中定义的事务属性,实质上就是在描述一个方法或者类应当如何参与到事务管理中来。具体来说,TransactionAttribute的主要作用有:

  1. 事务传播行为(Propagation)定义当调用的方法在一个已经存在的事务上下文中执行时,是应该加入当前事务、新建一个事务、挂起当前事务还是禁止事务等。比如PROPAGATION_REQUIRED表示如果当前存在事务,则加入该事务,否则创建一个新的事务
  2. 隔离级别(Isolation)指定事务的隔离级别,以防止不同事务之间的出现相互影响的情况。比如ISOLATION_READ_COMMITTED表示事务只能读取到其他事务已提交的数据,避免脏读现象
  3. 事务超时(Timeout)设置事务允许执行的最长时间,超过这个时间后事务将自动回滚
  4. 只读标志(ReadOnly)标记事务是否为只读事务,对于某些数据库,只读事务可以优化资源使用,并且可能不允许执行更新操作
  5. 事务回滚规则(Rollback Rules)定义哪些异常会导致事务回滚,哪些异常即使抛出也不会导致事务回滚

这些属性组合在一起就形成了对事务完整控制策略的描述使得开发者能够根据业务需求灵活地控制事务边界及事务内部的行为。在Spring AOP的事务拦截器中,会根据TransactionAttribute定义的规则来管理和控制事务的生命周期。

最后再来看一下PlatformTransactionManager这个接口,该接口继承了TransactionManager接口,其有4个实现类,分别为AbstractPlatformTransactionManager、DataSourceTransactionManager、JdbcTransactionManager、JtaTransactionManager。个人理解它是一个管理接口。先看一下它的继承体系:

下面一起来梳理一下PlatformTransactionManager这个类的作用:这个类是Spring框架中事务管理的核心接口,它负责在不同的事务策略和不同的持久化技术之间提供一个统一的编程模型。具体来说,它的主要作用包括:

  1. 事务管理PlatformTransactionManager定义了如何开始、提交、回滚以及同步事务等基本操作。通过实现这个接口的具体类(如DataSourceTransactionManager、HibernateTransactionManager或JpaTransactionManager等),Spring可以与各种数据访问技术集成并管理其事务
  2. 事务边界控制根据事务属性(如传播行为、隔离级别、超时时间等)来确定事务的范围和生命周期,确保方法调用在正确的事务上下文中执行
  3. 资源协调在分布式事务环境中,PlatformTransactionManager的某些实现还能够与Java Transaction API (JTA) 或者特定数据库的XA协议配合,以支持跨多个数据库资源的全局事务管理
  4. 异常处理:根据事务规则决定何时应该回滚事务,例如当业务方法抛出未捕获的运行时异常或受检查异常时

总之,PlatformTransactionManager为Spring应用提供了灵活且可插拔的事务管理机制使得开发者无需关注底层数据存储的细节,就可以方便地进行声明式事务管理,从而专注于业务逻辑开发

至此我们把Spring事务涉及到的一些基本组件的其体系结构及其作用都梳理了一下(注意:这只是个人粗浅的认知,如果不全,还望各位大佬指正)。下一篇博文我们将根据《Spring 事务原理总结一》中的案例来梳理一下事务代码的执行流程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机器挖掘工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值