Spring 源码学习:事务管理机制 – wiki基地

Spring 源码学习:事务管理机制

Spring 的事务管理机制是其核心功能之一,它简化了事务管理,让开发者能够专注于业务逻辑的实现,而无需过多关注底层事务细节。本文将深入探讨 Spring 的事务管理机制,从源码角度剖析其实现原理,帮助读者更好地理解和使用 Spring 事务。

一、事务管理的基本概念

在深入 Spring 源码之前,我们需要先了解事务管理的一些基本概念:

  • 事务(Transaction): 事务是作为一个单一的逻辑工作单元执行的一系列操作。它具有四个关键特性,通常称为 ACID:

    • 原子性(Atomicity): 事务中的所有操作要么全部成功,要么全部失败,不存在部分执行的情况。
    • 一致性(Consistency): 事务必须保证数据库从一个一致的状态转换到另一个一致的状态。
    • 隔离性(Isolation): 并发执行的事务之间应该互相隔离,一个事务的执行不应该受到其他事务的影响。
    • 持久性(Durability): 事务一旦提交,其结果应该永久保存在数据库中,即使系统发生故障也不会丢失。
  • 事务管理器(Transaction Manager): 事务管理器负责管理事务的生命周期,包括事务的启动、提交、回滚等操作。它协调底层资源管理器(如数据库)以保证事务的 ACID 特性。

  • 事务隔离级别(Transaction Isolation Level): 事务隔离级别定义了并发事务之间的隔离程度,不同的隔离级别可以避免不同的并发问题,但同时也会影响性能。常见的隔离级别包括:

    • READ UNCOMMITTED: 允许读取未提交的数据,可能导致脏读。
    • READ COMMITTED: 只允许读取已提交的数据,可以避免脏读,但可能导致不可重复读。
    • REPEATABLE READ: 保证在同一个事务中多次读取相同的数据,结果始终一致,可以避免不可重复读,但可能导致幻读。
    • SERIALIZABLE: 强制事务串行执行,可以避免所有并发问题,但性能最低。
  • 事务传播行为(Transaction Propagation Behavior): 事务传播行为定义了一个方法调用另一个方法时,事务应该如何传播。常见的传播行为包括:

    • REQUIRED: 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
    • REQUIRES_NEW: 无论当前是否存在事务,都会创建一个新的事务,如果当前存在事务,则挂起当前事务。
    • SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。
    • NOT_SUPPORTED: 总是以非事务方式执行,如果当前存在事务,则挂起当前事务。
    • MANDATORY: 必须在一个已存在的事务中执行,如果当前没有事务,则抛出异常。
    • NEVER: 总是以非事务方式执行,如果当前存在事务,则抛出异常。
    • NESTED: 如果当前存在事务,则创建一个嵌套事务;如果当前没有事务,则创建一个新的事务。

二、Spring 事务管理架构

Spring 的事务管理架构主要包含以下几个核心组件:

  • PlatformTransactionManager 接口: 这是 Spring 事务管理器的核心接口,定义了事务管理的基本操作,如获取事务(getTransaction)、提交事务(commit)和回滚事务(rollback)。 Spring 提供了多种 PlatformTransactionManager 的实现,分别用于不同的持久化技术,例如:

    • DataSourceTransactionManager 用于 JDBC 数据源的事务管理。
    • HibernateTransactionManager 用于 Hibernate 的事务管理。
    • JpaTransactionManager 用于 JPA 的事务管理。
    • JmsTransactionManager 用于 JMS 的事务管理。
  • TransactionDefinition 接口: 该接口定义了事务的属性,如隔离级别、传播行为、超时时间等。

  • TransactionStatus 接口: 该接口表示一个事务的状态,提供了访问事务状态的方法,如是否新事务、是否只读等。

  • TransactionInterceptor 类: 这是一个 AOP 拦截器,负责在方法执行前后进行事务管理,它使用 PlatformTransactionManager 来管理事务。

  • @Transactional 注解: 这是一个声明式事务管理的注解,开发者可以使用该注解来指定需要进行事务管理的方法或类。Spring AOP 会自动拦截带有该注解的方法,并使用 TransactionInterceptor 来管理事务。

三、Spring 事务管理源码剖析

接下来,我们将深入源码,分析 Spring 事务管理的核心实现原理。

1. PlatformTransactionManager 接口及其实现

PlatformTransactionManager 接口定义了事务管理的基本操作:

“`java
public interface PlatformTransactionManager {

// 获取事务
TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;

// 提交事务
void commit(TransactionStatus status) throws TransactionException;

// 回滚事务
void rollback(TransactionStatus status) throws TransactionException;

}
“`

DataSourceTransactionManager 为例,我们来看看它的 getTransaction 方法的实现:

“`java
@Override
public TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {

// 1. 获取当前线程的事务上下文
DataSourceTransactionObject txObject = (DataSourceTransactionObject) doGetTransaction();

// 2. 如果当前存在事务,则进行处理
if (txObject.hasConnectionHolder() &&
        !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
    TransactionSynchronizationManager.registerSynchronization(
            new ConnectionSynchronization(txObject.getConnectionHolder().getConnection(), getDataSource()));
    txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
}

// 3. 如果没有事务,或者需要创建新的事务
if (definition == null ||
        (!(definition instanceof DefaultTransactionDefinition) ||
        ((DefaultTransactionDefinition) definition).isReadOnly() == txObject.isReadOnly() &&
        definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED)) {
    return existingTransaction(definition, txObject);
}

// 4. 创建新的事务
return startNewTransaction(definition, txObject);

}
“`

getTransaction 方法首先获取当前线程的事务上下文,如果当前存在事务,则进行处理。如果不存在事务,则根据 TransactionDefinition 的属性来决定是否创建新的事务。

DataSourceTransactionManagercommit 方法的实现如下:

“`java
@Override
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);
}

}
“`

commit 方法获取当前事务的 Connection 对象,并调用 Connection.commit() 方法来提交事务。

DataSourceTransactionManagerrollback 方法的实现如下:

“`java
@Override
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 {
    con.rollback();
}
catch (SQLException ex) {
    throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
}

}
“`

rollback 方法获取当前事务的 Connection 对象,并调用 Connection.rollback() 方法来回滚事务。

2. TransactionInterceptor

TransactionInterceptor 是一个 AOP 拦截器,负责在方法执行前后进行事务管理。它的 invoke 方法的实现如下:

“`java
@Override
@Nullable
public Object invoke(final MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass,
        new InvocationCallback() {
            @Override
            public Object proceedWithInvocation() throws Throwable {
                return invocation.proceed();
            }
        });

}
“`

invoke 方法首先获取目标类,然后调用 invokeWithinTransaction 方法来执行事务管理逻辑。

invokeWithinTransaction 方法的实现如下:

“`java
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {

// 1. 获取事务属性
TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
PlatformTransactionManager tm = determineTransactionManager(txAttr);

final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

if (txAttr == null || tm == null) {
    // No transactional aspect configured: simply invoke the target method.
    return invocation.proceedWithInvocation();
}

TransactionStatus txStatus = null;
try {
    // 2. 获取事务
    txStatus = tm.getTransaction(txAttr);

    // 3. 执行目标方法
    Object result = invocation.proceedWithInvocation();

    // 4. 提交事务
    commitTransactionAfterReturning(txStatus);
    return result;
}
catch (Throwable ex) {
    // 5. 回滚事务
    completeTransactionAfterThrowing(txStatus, ex);
    throw ex;
}
finally {
    // 6. 清理事务
    cleanupTransactionInfo(txStatus);
}

}
“`

invokeWithinTransaction 方法的执行流程如下:

  1. 获取事务属性,例如隔离级别、传播行为等。
  2. 获取事务管理器。
  3. 获取事务。
  4. 执行目标方法。
  5. 如果目标方法执行成功,则提交事务。
  6. 如果目标方法抛出异常,则回滚事务。
  7. 清理事务。

3. @Transactional 注解

@Transactional 注解是 Spring 声明式事务管理的核心。当 Spring 容器扫描到带有 @Transactional 注解的类或方法时,会自动为这些类或方法创建 AOP 代理,并在方法执行前后进行事务管理。

Spring 使用 TransactionAttributeSource 来解析 @Transactional 注解,获取事务属性。常见的 TransactionAttributeSource 实现包括:

  • AnnotationTransactionAttributeSource@Transactional 注解中获取事务属性。
  • AttributesTransactionAttributeSource 从配置的属性文件中获取事务属性。

四、Spring 事务传播行为源码分析

Spring 事务传播行为的实现主要体现在 TransactionInterceptorinvokeWithinTransaction 方法中,它会根据 TransactionDefinition 中的 propagationBehavior 属性来决定如何处理事务。

例如,当 propagationBehaviorREQUIRED 时,invokeWithinTransaction 方法的逻辑如下:

“`java
if (txAttr == null || tm == null) {
// No transactional aspect configured: simply invoke the target method.
return invocation.proceedWithInvocation();
}

TransactionStatus txStatus = null;
try {
// 2. 获取事务
txStatus = tm.getTransaction(txAttr);

// 3. 执行目标方法
Object result = invocation.proceedWithInvocation();

// 4. 提交事务
commitTransactionAfterReturning(txStatus);
return result;

}
catch (Throwable ex) {
// 5. 回滚事务
completeTransactionAfterThrowing(txStatus, ex);
throw ex;
}
finally {
// 6. 清理事务
cleanupTransactionInfo(txStatus);
}
“`

可以看到,如果当前存在事务,则 tm.getTransaction(txAttr) 方法会加入该事务;如果当前没有事务,则 tm.getTransaction(txAttr) 方法会创建一个新的事务。

propagationBehaviorREQUIRES_NEW 时,invokeWithinTransaction 方法的逻辑会更加复杂,它需要挂起当前事务,并创建一个新的事务。

五、总结

本文深入分析了 Spring 事务管理的架构和源码,从 PlatformTransactionManager 接口及其实现,到 TransactionInterceptor 类和 @Transactional 注解,都进行了详细的讲解。通过阅读本文,读者可以更好地理解 Spring 事务管理的实现原理,并能够更加灵活地使用 Spring 事务来保证数据的一致性和完整性。

Spring 的事务管理机制是一个复杂而精巧的系统,它充分利用了 AOP 和接口编程的思想,为开发者提供了一种简单而强大的事务管理方案。希望本文能够帮助读者更深入地理解 Spring 事务管理,并在实际开发中更好地应用它。

六、进阶学习建议

  • 深入研究 TransactionSynchronizationManager 类,了解 Spring 如何管理线程相关的事务上下文。
  • 了解 Spring 的事务隔离级别和并发问题的解决方案。
  • 研究不同的 PlatformTransactionManager 实现,例如 HibernateTransactionManagerJpaTransactionManager
  • 尝试自定义 TransactionAttributeSource,以实现更灵活的事务属性配置。
  • 阅读 Spring 官方文档,了解更多关于 Spring 事务管理的信息。

通过不断学习和实践,您将能够更加深入地理解 Spring 事务管理机制,并能够更加自信地应对各种复杂的事务场景。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部