Skip to content

03.4 事务高级特性

本章覆盖 TransactionSynchronizationManager 线程绑定核心、回滚规则的深度匹配算法、@Transactional 注解解析流程、readOnly 只读优化的 JDBC + Hibernate 双层面实现,以及完整流程总结。


1. TransactionSynchronizationManager — 事务同步管理器

这是 Spring 事务的线程绑定核心,维护了当前线程的事务上下文。

java
public abstract class TransactionSynchronizationManager {
    
    // 1. 当前线程绑定的数据源连接资源    
    // key: DataSource (资源工厂)
    // value: ConnectionHolder (连接持有者)
    private static final ThreadLocal<Map<Object, Object>> resources = 
        new NamedThreadLocal<>("Transactional resources");
    
    // 2. 当前线程的同步器列表
    private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations = 
        new NamedThreadLocal<>("Transaction synchronizations");
    
    // 3. 当前事务的名称
    private static final ThreadLocal<String> currentTransactionName = 
        new NamedThreadLocal<>("Current transaction name");
    
    // 4. 当前事务的只读状态
    private static final ThreadLocal<Boolean> currentTransactionReadOnly = 
        new NamedThreadLocal<>("Current transaction read-only status");
    
    // 5. 当前事务的隔离级别
    private static final ThreadLocal<Integer> currentTransactionIsolationLevel = 
        new NamedThreadLocal<>("Current transaction isolation level");
    
    // 6. 当前事务是否活跃
    private static final ThreadLocal<Boolean> actualTransactionActive = 
        new NamedThreadLocal<>("Actual transaction active");
}

1.1 线程绑定机制

1.2 事务同步器机制

java
// 事务同步器接口 — 允许在事务生命周期各阶段加入自定义逻辑
public interface TransactionSynchronization extends Ordered, Flushable {
    
    int STATUS_COMMITTED = 0;    // 事务已提交
    int STATUS_ROLLED_BACK = 1;  // 事务已回滚
    int STATUS_UNKNOWN = 2;      // 状态未知
    
    // 事务挂起时回调
    default void suspend() {}
    
    // 事务恢复时回调
    default void resume() {}
    
    // flush 操作(事务提交前)
    default void flush() {}
    
    // 事务提交前(beforeCommit → beforeCompletion → commit → afterCommit → afterCompletion)
    default void beforeCommit(boolean readOnly) {}
    default void beforeCompletion() {}
    default void afterCommit() {}
    default void afterCompletion(int status) {}
}

1.3 同步器的执行顺序

java
// AbstractPlatformTransactionManager.processCommit()
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
    try {
        // 1. 事务提交前的钩子
        triggerBeforeCommit(status);
        // 2. 事务完成前的钩子
        triggerBeforeCompletion();
        // 3. 实际提交(根据是否有保存点区分)
        if (status.hasSavepoint()) {
            // NESTED:释放保存点
            status.releaseHeldSavepoint();
        } else if (status.isNewTransaction()) {
            // 新事务:直接提交
            doCommit(status);
        }
        // 4. 提交后的钩子(注意:此时事务可能还没完全结束)
        triggerAfterCommit(status);
    } finally {
        // 5. 最终完成后的钩子(一定会执行)
        triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
    }
}

2. 回滚规则机制

java
// TransactionAttribute 中定义了回滚规则
public interface TransactionAttribute extends TransactionDefinition {
    
    // 获取需要回滚的异常类型列表(rollbackFor)
    Collection<Class<? extends Throwable>> rollbackOn();
    
    // 获取不需要回滚的异常类型列表(noRollbackFor)
    Collection<Class<? extends Throwable>> noRollbackOn();
    
    // 判断给定异常是否应该触发回滚
    // 这是 Spring 判断回滚的核心方法
    default boolean rollbackOn(Throwable ex) {
        // 委托给 RollbackRuleAttribute 链处理
        return getRollbackRules().stream()
            .map(rule -> rule.getDepth(ex))
            .filter(depth -> depth >= 0)
            .min(Integer::compareTo)
            .map(depth -> /* 最后一个匹配的规则决定 */)
            .orElse(false);  // 无匹配 → 不回滚
    }
}

RuleBasedTransactionAttribute 的 rollbackOn 源码

java
public class RuleBasedTransactionAttribute extends DefaultTransactionAttribute implements Serializable {
    
    private List<RollbackRuleAttribute> rollbackRules;
    
    @Override
    public boolean rollbackOn(Throwable ex) {
        if (logger.isTraceEnabled()) {
            logger.trace("Applying rules to determine whether transaction should rollback on " + ex);
        }
        
        // 获取回滚规则列表
        RollbackRuleAttribute winner = null;
        int deepest = Integer.MAX_VALUE;
        
        if (this.rollbackRules != null) {
            for (RollbackRuleAttribute rule : this.rollbackRules) {
                // 计算异常与规则的匹配深度
                // 规则可以是 "java.lang.Exception" 这样的异常类名
                int depth = rule.getDepth(ex);
                if (depth >= 0 && depth < deepest) {
                    deepest = depth;
                    winner = rule;
                }
            }
        }
        
        if (logger.isTraceEnabled()) {
            logger.trace("Winning rollback rule is: " + winner);
        }
        
        if (winner == null) {
            // 没有匹配到任何规则 → 使用默认行为
            // 默认行为:只回滚 RuntimeException 和 Error
            logger.trace("No relevant rollback rule found: applying default rules");
            return ex instanceof RuntimeException || ex instanceof Error;
        }
        
        // 根据匹配到的规则决定
        // RollbackRuleAttribute → 回滚
        // NoRollbackRuleAttribute → 不回滚
        return !(winner instanceof NoRollbackRuleAttribute);
    }
}

getDepth 匹配逻辑

java
public class RollbackRuleAttribute implements Serializable {
    
    public static final RollbackRuleAttribute ROLLBACK_ON_RUNTIME_EXCEPTIONS = 
        new RollbackRuleAttribute(RuntimeException.class);
    
    private final String exceptionName;
    
    public RollbackRuleAttribute(Class<?> clazz) {
        this.exceptionName = clazz.getName();
    }
    
    // 深度计算:异常类名与规则类名的继承距离
    public int getDepth(Throwable ex) {
        return getDepth(ex.getClass(), 0);
    }
    
    private int getDepth(Class<?> exceptionClass, int depth) {
        if (exceptionClass.getName().contains(this.exceptionName)) {
            // 找到了匹配的祖先类
            return depth;
        }
        if (exceptionClass == Throwable.class) {
            // 查到了根,没有匹配
            return -1;
        }
        // 向上递归查找父类
        return getDepth(exceptionClass.getSuperclass(), depth + 1);
    }
}

3. @Transactional 注解解析流程

java
// TransactionAnnotationParser 接口
public interface TransactionAnnotationParser {
    @Nullable
    TransactionAttribute parseTransactionAnnotation(AnnotatedElement element);
}

// SpringTransactionAnnotationParser(核心实现)
public class SpringTransactionAnnotationParser implements TransactionAnnotationParser {
    
    @Override
    @Nullable
    public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
        // 查找 @Transactional 注解(支持 @AliasFor 别名机制)
        Transactional annotation = AnnotatedElementUtils.findMergedAnnotation(
            element, Transactional.class);
        
        if (annotation != null) {
            return parseTransactionAnnotation(annotation);
        }
        return null;
    }
    
    // 将 @Transactional 注解属性解析成 TransactionAttribute
    protected TransactionAttribute parseTransactionAnnotation(Transactional annotation) {
        RuleBasedTransactionAttribute attr = new RuleBasedTransactionAttribute();
        
        // 传播行为
        attr.setPropagationBehavior(annotation.propagation());
        // 隔离级别
        attr.setIsolationLevel(annotation.isolation());
        // 超时(默认 -1,即使用数据库默认)
        attr.setTimeout(annotation.timeout());
        // 只读
        attr.setReadOnly(annotation.readOnly());
        // 限定符
        attr.setQualifier(annotation.value());
        
        // 回滚规则:rollbackFor → RollbackRuleAttribute
        List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
        for (Class<?> rbRule : annotation.rollbackFor()) {
            rollbackRules.add(new RollbackRuleAttribute(rbRule));
        }
        for (String rbRule : annotation.rollbackForClassName()) {
            rollbackRules.add(new RollbackRuleAttribute(rbRule));
        }
        // 不回滚规则:noRollbackFor → NoRollbackRuleAttribute
        for (Class<?> rbRule : annotation.noRollbackFor()) {
            rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
        }
        for (String rbRule : annotation.noRollbackForClassName()) {
            rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
        }
        
        attr.setRollbackRules(rollbackRules);
        return attr;
    }
}

4. 事务只读深入 — readOnly 的底层实现

java
// DataSourceTransactionManager.prepareTransactional()
protected void prepareTransactional(Connection con, TransactionDefinition definition) {
    if (definition.isReadOnly()) {
        try {
            // 1. 对 JDBC 层设置只读 hint
            //    部分数据库(如 MySQL)会利用这个提示做优化
            con.setReadOnly(true);
        } catch (SQLException ex) {
            // 如果数据库不支持(如 Oracle 在某些驱动版本下),忽略
            // 所以 readOnly 是 "best effort" 的
        }
    }
}

Hibernate 层面的只读优化

java
// HibernateJpaDialect.beginTransaction()
@Override
public Transaction beginTransaction(EntityManager entityManager, TransactionDefinition definition) {
    if (definition.isReadOnly()) {
        // 设置 Hibernate 的查询模式
        Session session = entityManager.unwrap(Session.class);
        
        // 关键:设置 FlushMode = MANUAL
        // 这意味着 Hibernate 不会自动做脏检查(dirty checking)
        // 也不会自动 flush 到数据库,大幅减少快照比较的开销
        session.setHibernateFlushMode(FlushMode.MANUAL);
        
        // 设置只读实体(可选优化)
        // Hibernate 会跳过对这些实体的脏检查
    }
    return super.beginTransaction(entityManager, definition);
}

5. 完整事务流程总结

java
// 以 @Transactional 标注方法为例
@Service
public class OrderService {
    
    @Transactional(propagation = Propagation.REQUIRED, 
                   isolation = Isolation.READ_COMMITTED,
                   rollbackFor = Exception.class,
                   readOnly = false)
    public void createOrder(OrderRequest request) {
        // 业务代码
    }
}

完整调用链

  1. 客户端调用orderService.createOrder(request)(注入的是 AOP 代理对象)
  2. TransactionInterceptor.invoke() — AOP 拦截入口
  3. TransactionAspectSupport.invokeWithinTransaction() — 事务核心方法
  4. 解析 @Transactional 属性 → 构建 RuleBasedTransactionAttribute
  5. 确定事务管理器 → 通常是 DataSourceTransactionManager
  6. DataSourceTransactionManager.getTransaction()
    • doGetTransaction() → 从 TransactionSynchronizationManager 获取当前线程的 ConnectionHolder
    • 检查是否已有事务 → 根据传播行为处理
    • doBegin() → 从连接池获取新连接 → con.setAutoCommit(false) → 绑定到线程
  7. 执行业务方法invocation.proceed()(所有 DAO 操作使用同一连接)
  8. 提交/回滚
    • 正常返回 → processCommit()triggerBeforeCommit()doCommit(con.commit())triggerAfterCommit()
    • 异常 → completeTransactionAfterThrowing()rollbackOn() 判断 → doRollback(con.rollback())
  9. 清理doCleanupAfterCompletion() → 解绑连接 → con.setAutoCommit(true) → 归还连接池

核心面试题

  1. TransactionSynchronizationManager 的作用?Spring 如何实现事务的线程隔离?
  2. @Transactional(rollbackFor = Exception.class) 和默认行为有什么区别?Spring 如何判断一个异常是否该回滚?
  3. readOnly = true 的底层优化机制(提示:JDBC + Hibernate 两个层面)?
  4. Spring 声明式事务的底层实现原理?从 @Transactional 到数据库 commit() 的完整调用链?

← 返回 **返回 事务管理索引**

Knowledge4J — Java 知识库