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) {
// 业务代码
}
}完整调用链
- 客户端调用 →
orderService.createOrder(request)(注入的是 AOP 代理对象) TransactionInterceptor.invoke()— AOP 拦截入口TransactionAspectSupport.invokeWithinTransaction()— 事务核心方法- 解析
@Transactional属性 → 构建RuleBasedTransactionAttribute - 确定事务管理器 → 通常是
DataSourceTransactionManager DataSourceTransactionManager.getTransaction()doGetTransaction()→ 从TransactionSynchronizationManager获取当前线程的ConnectionHolder- 检查是否已有事务 → 根据传播行为处理
doBegin()→ 从连接池获取新连接 →con.setAutoCommit(false)→ 绑定到线程
- 执行业务方法 →
invocation.proceed()(所有 DAO 操作使用同一连接) - 提交/回滚
- 正常返回 →
processCommit()→triggerBeforeCommit()→doCommit(con.commit())→triggerAfterCommit() - 异常 →
completeTransactionAfterThrowing()→rollbackOn()判断 →doRollback(con.rollback())
- 正常返回 →
- 清理 →
doCleanupAfterCompletion()→ 解绑连接 →con.setAutoCommit(true)→ 归还连接池
核心面试题
TransactionSynchronizationManager的作用?Spring 如何实现事务的线程隔离?@Transactional(rollbackFor = Exception.class)和默认行为有什么区别?Spring 如何判断一个异常是否该回滚?- readOnly = true 的底层优化机制(提示:JDBC + Hibernate 两个层面)?
- Spring 声明式事务的底层实现原理?从
@Transactional到数据库commit()的完整调用链?
← 返回 **返回 事务管理索引**