在白嫖之前,希望你会内疚,最起码点个赞收藏再自取吧,源码在最后,自取;
在白嫖之前,希望你会内疚,最起码点个赞收藏再自取吧,源码在最后,自取;
在白嫖之前,希望你会内疚,最起码点个赞收藏再自取吧,源码在最后,自取;
本文从底层原理+核心代码 角度,拆解AOP实现事务控制的完整逻辑,重点分析Spring事务管理器(PlatformTransactionManager)的核心实现,以及AOP如何通过环绕通知织入事务逻辑。所有代码均为可理解的核心简化版,保留Spring原生逻辑但剔除冗余,便于学习核心思路。
一、核心前置知识
1. 事务的本质(数据库层面)
事务的底层是数据库连接(java.sql.Connection)的特性:
- 默认
autoCommit=true:执行每条SQL后自动提交; - 开启事务:
connection.setAutoCommit(false); - 提交:
connection.commit(); - 回滚:
connection.rollback()。
Spring事务的本质是通过AOP拦截方法,统一管理数据库连接的事务状态,让业务代码无需感知连接操作。
2. AOP实现事务的核心角色
| 角色 | 作用 |
|---|---|
事务管理器(PlatformTransactionManager) |
封装事务的开启/提交/回滚逻辑(对接数据库连接) |
事务拦截器(TransactionInterceptor) |
AOP环绕通知的核心实现,触发事务管理器操作 |
| 动态代理(JDK/CGLIB) | 为业务类生成代理对象,接管方法调用 |
事务注解(@Transactional) |
标记需要事务增强的方法,定义事务属性(传播行为、隔离级别等) |
二、手写简化版AOP事务框架(理解底层)
先通过手写核心代码模拟Spring事务的实现逻辑,掌握AOP+事务的核心思路。
步骤1:定义事务注解(模拟@Transactional)
java
import java.lang.annotation.*;
/**
* 自定义事务注解,标记需要事务控制的方法
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyTransactional {
// 模拟事务传播行为(简化版)
Propagation propagation() default Propagation.REQUIRED;
// 事务隔离级别(简化版)
Isolation isolation() default Isolation.DEFAULT;
// 异常回滚规则
Class<? extends Throwable>[] rollbackFor() default {Exception.class};
}
// 传播行为枚举(简化)
enum Propagation {
REQUIRED // 默认:有事务则加入,无则新建
}
// 隔离级别枚举(简化)
enum Isolation {
DEFAULT // 使用数据库默认隔离级别
}
步骤2:实现事务管理器(模拟DataSourceTransactionManager)
java
import org.springframework.jdbc.datasource.DataSourceUtils;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
/**
* 自定义事务管理器:封装数据库连接的事务操作
* 核心:绑定连接到当前线程(ThreadLocal),保证同线程内方法共用一个连接
*/
public class MyTransactionManager {
// 数据源(Spring中通过配置注入)
private final DataSource dataSource;
// 线程本地变量:存储当前线程的事务连接+状态
private final ThreadLocal<TransactionInfo> threadLocal = new ThreadLocal<>();
public MyTransactionManager(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 开启事务
*/
public TransactionInfo begin(MyTransactional annotation) {
// 1. 获取数据库连接(Spring中通过DataSourceUtils保证线程绑定)
Connection conn = DataSourceUtils.getConnection(dataSource);
TransactionInfo txInfo = new TransactionInfo();
txInfo.setConn(conn);
txInfo.setAnnotation(annotation);
txInfo.setOldAutoCommit(true); // 保存原有autoCommit状态
try {
// 2. 关闭自动提交,开启事务
if (conn.getAutoCommit()) {
conn.setAutoCommit(false);
txInfo.setOldAutoCommit(true);
}
// 3. 设置隔离级别(简化版)
if (annotation.isolation() != Isolation.DEFAULT) {
conn.setTransactionIsolation(annotation.isolation().ordinal() + 1);
}
// 4. 将事务信息绑定到当前线程
threadLocal.set(txInfo);
return txInfo;
} catch (SQLException e) {
throw new RuntimeException("开启事务失败", e);
}
}
/**
* 提交事务
*/
public void commit(TransactionInfo txInfo) {
if (txInfo == null) return;
Connection conn = txInfo.getConn();
try {
if (conn != null && !conn.isClosed()) {
conn.commit(); // 提交事务
// 恢复原有autoCommit状态
conn.setAutoCommit(txInfo.isOldAutoCommit());
}
} catch (SQLException e) {
throw new RuntimeException("提交事务失败", e);
} finally {
// 释放连接+清空线程变量
DataSourceUtils.releaseConnection(conn, dataSource);
threadLocal.remove();
}
}
/**
* 回滚事务
*/
public void rollback(TransactionInfo txInfo) {
if (txInfo == null) return;
Connection conn = txInfo.getConn();
try {
if (conn != null && !conn.isClosed()) {
conn.rollback(); // 回滚事务
conn.setAutoCommit(txInfo.isOldAutoCommit());
}
} catch (SQLException e) {
throw new RuntimeException("回滚事务失败", e);
} finally {
DataSourceUtils.releaseConnection(conn, dataSource);
threadLocal.remove();
}
}
// 事务信息封装类
public static class TransactionInfo {
private Connection conn;
private MyTransactional annotation;
private boolean oldAutoCommit;
// getter/setter 省略
}
}
步骤3:实现AOP环绕通知(事务拦截器)
java
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import java.lang.reflect.Method;
/**
* 自定义事务拦截器:AOP环绕通知核心逻辑
* 作用:拦截@MyTransactional注解的方法,织入事务开启/提交/回滚逻辑
*/
@Aspect
public class MyTransactionInterceptor {
// 事务管理器(Spring中通过依赖注入)
private final MyTransactionManager transactionManager;
public MyTransactionInterceptor(MyTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
/**
* 环绕通知:拦截所有标注@MyTransactional的方法
*/
@Around("@annotation(com.example.MyTransactional)")
public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable {
// 1. 获取方法上的事务注解
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
MyTransactional annotation = method.getAnnotation(MyTransactional.class);
MyTransactionManager.TransactionInfo txInfo = null;
try {
// 2. 开启事务
txInfo = transactionManager.begin(annotation);
// 3. 执行原始业务方法(核心:调用目标方法)
Object result = joinPoint.proceed();
// 4. 提交事务
transactionManager.commit(txInfo);
return result;
} catch (Throwable e) {
// 5. 异常回滚(判断是否符合回滚规则)
if (isRollback(e, annotation.rollbackFor())) {
transactionManager.rollback(txInfo);
}
throw e; // 抛出异常,上层可感知
}
}
/**
* 判断异常是否需要回滚
*/
private boolean isRollback(Throwable e, Class<? extends Throwable>[] rollbackFor) {
for (Class<? extends Throwable> clazz : rollbackFor) {
if (clazz.isInstance(e)) {
return true;
}
}
return false;
}
}
步骤4:配置类(开启AOP+注入组件)
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
/**
* 配置类:组装AOP事务的核心组件
*/
@Configuration
@EnableAspectJAutoProxy // 开启AOP动态代理
public class TransactionConfig {
// 1. 配置数据源
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test?useSSL=false");
dataSource.setUsername("root");
dataSource.setPassword("123456");
return dataSource;
}
// 2. 配置自定义事务管理器
@Bean
public MyTransactionManager myTransactionManager(DataSource dataSource) {
return new MyTransactionManager(dataSource);
}
// 3. 配置事务拦截器(AOP切面)
@Bean
public MyTransactionInterceptor myTransactionInterceptor(MyTransactionManager transactionManager) {
return new MyTransactionInterceptor(transactionManager);
}
}
步骤5:业务层使用自定义事务注解
java
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@Service
public class OrderService {
@Resource
private DataSource dataSource;
/**
* 标记需要事务控制的业务方法
*/
@MyTransactional(rollbackFor = {Exception.class})
public void createOrder(Long productId, Integer num) throws SQLException {
// 业务逻辑1:扣减库存
deductStock(productId, num);
// 业务逻辑2:创建订单(模拟异常:如果num>10则抛异常,触发回滚)
if (num > 10) {
throw new RuntimeException("库存超出限制");
}
createOrderRecord(productId, num);
}
// 扣减库存
private void deductStock(Long productId, Integer num) throws SQLException {
String sql = "UPDATE stock SET num = num - ? WHERE product_id = ?";
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, num);
ps.setLong(2, productId);
ps.executeUpdate();
}
}
// 创建订单记录
private void createOrderRecord(Long productId, Integer num) throws SQLException {
String sql = "INSERT INTO `order` (product_id, num) VALUES (?, ?)";
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setLong(1, productId);
ps.setInt(2, num);
ps.executeUpdate();
}
}
}
手写版核心逻辑总结
- 注解标记 :通过
@MyTransactional标记需要事务的方法; - AOP拦截:环绕通知拦截目标方法,触发事务逻辑;
- 事务管理器 :封装数据库连接的
autoCommit、commit、rollback操作; - 线程绑定 :通过
ThreadLocal保证同线程内的业务方法共用一个数据库连接(核心!否则多方法会用不同连接,事务失效)。
三、Spring原生事务管理器深度解析
Spring的PlatformTransactionManager是事务管理的核心接口,我们基于手写版对比,分析其原生实现。
1. 核心接口体系
java
// Spring事务管理器顶级接口
public interface PlatformTransactionManager {
// 获取事务(开启事务)
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
// 提交事务
void commit(TransactionStatus status) throws TransactionException;
// 回滚事务
void rollback(TransactionStatus status) throws TransactionException;
}
// 事务定义(传播行为、隔离级别、超时时间等)
public interface TransactionDefinition {
int PROPAGATION_REQUIRED = 0; // 默认传播行为
int ISOLATION_DEFAULT = -1; // 默认隔离级别
// 省略其他常量+方法
}
// 事务状态(封装事务的连接、是否新建、是否回滚等)
public interface TransactionStatus extends SavepointManager {
boolean isNewTransaction(); // 是否是新建事务
boolean hasSavepoint(); // 是否有保存点
void setRollbackOnly(); // 标记为回滚
boolean isRollbackOnly(); // 是否需要回滚
void flush(); // 刷新事务
boolean isCompleted(); // 事务是否完成
}
2. 核心实现类:DataSourceTransactionManager
DataSourceTransactionManager是JDBC/MyBatis场景下的核心实现,核心方法拆解:
(1)开启事务:getTransaction()
java
@Override
public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
// 1. 获取事务定义(传播行为、隔离级别等)
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
// 2. 获取数据源连接(绑定到当前线程)
Object transaction = doGetTransaction();
boolean debugEnabled = logger.isDebugEnabled();
// 3. 处理传播行为(核心:判断是否新建事务/加入已有事务)
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED) {
// 检查当前线程是否已有事务
if (isExistingTransaction(transaction)) {
// 有事务则加入(复用连接)
return handleExistingTransaction(def, transaction, debugEnabled);
}
// 无事务则新建
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
}
// 4. 开启新事务(核心:获取连接+关闭autoCommit)
return startNewTransaction(def, transaction, debugEnabled);
}
// 省略其他传播行为的处理...
}
// 核心:开启新事务
private TransactionStatus startNewTransaction(TransactionDefinition definition, Object transaction, boolean debugEnabled) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
// 5. 获取数据库连接(通过DataSourceUtils,保证线程绑定)
Connection conn = DataSourceUtils.getConnection(obtainDataSource());
txObject.setConnectionHolder(new ConnectionHolder(conn), true);
// 6. 关闭自动提交,开启事务
try {
if (conn.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
if (debugEnabled) {
logger.debug("Switching JDBC Connection [" + conn + "] to manual commit");
}
conn.setAutoCommit(false);
}
// 7. 设置隔离级别
prepareTransactionalConnection(conn, definition);
// 8. 标记事务为新建
txObject.setNewTransaction(true);
if (definition.isReadOnly()) {
txObject.setReadOnly(true);
}
// 9. 返回事务状态
return new DefaultTransactionStatus(
txObject, true, false, definition.isReadOnly(), debugEnabled, null);
} catch (SQLException ex) {
DataSourceUtils.releaseConnection(conn, obtainDataSource());
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}
(2)提交事务:commit()
java
@Override
public void commit(TransactionStatus status) throws TransactionException {
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
// 1. 如果已标记回滚,则直接回滚
if (defStatus.isRollbackOnly()) {
processRollback(defStatus, false);
return;
}
// 2. 非新建事务则不提交(交给外层事务处理)
if (!defStatus.isNewTransaction()) {
if (defStatus.hasTransaction()) {
if (defStatus.isDebug()) {
logger.debug("Not committing JDBC transaction because it's not a new transaction");
}
}
return;
}
// 3. 新建事务则提交
try {
doCommit(defStatus);
} catch (SQLException ex) {
throw new TransactionSystemException("Could not commit JDBC transaction", ex);
} finally {
// 4. 释放连接+恢复autoCommit
cleanupAfterCompletion(defStatus.getTransaction());
}
}
// 实际提交逻辑
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);
}
}
(3)回滚事务:rollback()
java
@Override
public void rollback(TransactionStatus status) throws TransactionException {
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
// 1. 非新建事务则标记回滚(交给外层处理)
if (!defStatus.isNewTransaction()) {
if (defStatus.hasTransaction()) {
if (defStatus.isDebug()) {
logger.debug("Setting JDBC transaction rollback-only");
}
defStatus.setRollbackOnly();
}
return;
}
// 2. 新建事务则直接回滚
processRollback(defStatus, false);
}
// 实际回滚逻辑
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
try {
boolean rollback = true;
// 处理保存点(简化版忽略)
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Rolling back JDBC transaction to savepoint");
}
status.rollbackToSavepoint();
rollback = false;
}
// 3. 回滚事务
if (rollback) {
doRollback(status);
}
} catch (SQLException ex) {
throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
} finally {
// 4. 释放连接+恢复autoCommit
cleanupAfterCompletion(status.getTransaction());
}
}
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);
}
}
3. Spring事务管理器核心设计思路
| 设计点 | 作用 |
|---|---|
接口抽象(PlatformTransactionManager) |
解耦事务逻辑与具体数据库类型(支持JDBC、JPA、Hibernate等) |
线程绑定(TransactionSynchronizationManager) |
通过ThreadLocal存储当前线程的事务连接、事务状态,保证同线程内方法共用连接 |
| 传播行为处理 | 支持REQUIRED、REQUIRES_NEW等传播行为,灵活控制事务范围 |
| 异常兼容 | 封装数据库异常为Spring统一的TransactionException,简化异常处理 |
四、AOP+事务管理器的完整执行流程(Spring原生)
结合前面的分析,梳理Spring中AOP实现事务的完整流程:
- 启动阶段 :
@EnableTransactionManagement开启事务注解驱动;- Spring扫描
@Transactional注解,为目标类创建动态代理; - 注册
TransactionInterceptor(事务拦截器,实现MethodInterceptor)。
- 运行阶段:
- Controller调用业务方法 → 代理对象拦截方法调用;
- 触发
TransactionInterceptor.invoke(); - 调用
TransactionManager.getTransaction()开启事务; TransactionManager获取连接+关闭autoCommit;- 执行原始业务方法;
- 业务执行成功 →
TransactionManager.commit()提交事务; - 业务执行异常 →
TransactionManager.rollback()回滚事务; - 释放连接+恢复
autoCommit; - 返回结果给Controller。
五、常见问题与核心注意点
- 事务失效的核心原因 :
- 方法非public(AOP无法拦截非public方法);
- 内部调用(代理对象无法拦截,如
service.a()调用service.b(),b()的事务失效); - 线程池异步调用(不同线程无法共享
ThreadLocal中的连接); - 异常被捕获(未抛出到拦截器,无法触发回滚)。
- ThreadLocal的核心作用 :
没有ThreadLocal,不同方法会获取不同的数据库连接,事务无法覆盖多个方法(这是事务管理的核心!)。 - 传播行为的本质 :
传播行为是通过判断当前线程是否已有事务连接,决定"新建连接"或"复用连接"。
六、学习建议
- 先运行手写版代码,理解"注解+AOP+事务管理器+ThreadLocal"的核心;
- 阅读Spring源码:
- 入口:
TransactionInterceptor.invoke(); - 核心类:
DataSourceTransactionManager、TransactionSynchronizationManager;
- 入口:
- 调试事务失效场景(如内部调用、异常捕获),加深对代理和线程绑定的理解。
总结
Spring中AOP实现事务管理的核心流程可总结为:首先通过@EnableTransactionManagement开启事务注解驱动,Spring扫描到业务方法上的@Transactional注解后,为目标业务类创建动态代理对象;当调用方触发标注了@Transactional的业务方法时,实际调用的是代理对象的方法,此时AOP的事务拦截器(TransactionInterceptor)会触发环绕通知逻辑------先调用事务管理器(如DataSourceTransactionManager)的getTransaction()方法,从数据源获取连接并通过ThreadLocal绑定到当前线程,关闭连接的自动提交以开启事务;接着执行原始的业务方法逻辑,若业务执行无异常,事务管理器调用commit()提交事务,若抛出符合回滚规则的异常,则调用rollback()回滚事务;最后无论提交或回滚,都会释放数据库连接、恢复连接的自动提交状态,并清空ThreadLocal中的事务信息,整个过程通过AOP的代理和环绕通知,将事务的开启、提交/回滚逻辑与业务代码解耦,保证业务方法的原子性。