Spring事务源码
深入 Spring 事务的源码实现,重点结合 AOP(面向切面编程) 的机制,从代理创建、拦截器执行、事务开启到 ThreadLocal
状态管理,完整地走一遍核心流程。
文章目录
- 一、前置知识:Spring 事务 + AOP 的核心组件
- 二、启动阶段:`@EnableTransactionManagement` 的作用
- 1. `AutoProxyRegistrar`:注册自动代理机制
- 2. `ProxyTransactionManagementConfiguration`:配置事务基础设施
- 三、代理创建阶段:`AbstractAutoProxyCreator`
- 四、方法调用阶段:AOP 拦截与事务逻辑
- 1. 代理触发 `TransactionInterceptor.invoke()`
- 2. 核心:`TransactionAspectSupport.invokeWithinTransaction`
- 五、事务绑定到线程:`TransactionSynchronizationManager`
- 1. `AbstractPlatformTransactionManager.getTransaction()`
- 2. `DataSourceTransactionManager.doBegin()`:绑定连接
- 3. `TransactionSynchronizationManager.bindResource()` 源码
- 六、DAO 层如何获取事务连接?
- 七、自调用失效:AOP 视角
- 执行流程:
- 八、图解:AOP + 事务全流程
- 总结
一、前置知识:Spring 事务 + AOP 的核心组件
组件 | 作用 |
---|---|
@EnableTransactionManagement | 启用事务注解支持,导入 TransactionManagementConfigurationSelector |
ProxyTransactionManagementConfiguration | 配置事务相关的 Bean(如 TransactionInterceptor ) |
BeanPostProcessor | 在 Bean 初始化前后进行增强(创建代理) |
AbstractAutoProxyCreator | 自动代理创建器基类 |
InfrastructureAdvisorAutoProxyCreator | 为基础设施(如事务)创建代理 |
TransactionInterceptor | 核心拦截器,实现 MethodInterceptor ,负责事务逻辑 |
TransactionAspectSupport | 事务支持基类,包含 invokeWithinTransaction 核心方法 |
TransactionSynchronizationManager | 使用 ThreadLocal 管理事务资源(连接、状态等) |
二、启动阶段:@EnableTransactionManagement
的作用
@Configuration
@EnableTransactionManagement
public class AppConfig {
}
@EnableTransactionManagement
注解会导入:
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {@Overrideprotected String[] selectImports(AdviceMode adviceMode) {if (adviceMode == AdviceMode.PROXY) {// 默认使用代理模式return new String[] {AutoProxyRegistrar.class.getName(), // 注册自动代理ProxyTransactionManagementConfiguration.class.getName() // 配置事务相关 Bean};}// AspectJ 模式...}
}
1. AutoProxyRegistrar
:注册自动代理机制
- 它会向容器注册一个
InfrastructureAdvisorAutoProxyCreator
。 - 这个
BeanPostProcessor
会在 Bean 初始化后,判断是否需要创建代理。
2. ProxyTransactionManagementConfiguration
:配置事务基础设施
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {// 创建事务切面:Advisor = Pointcut + AdviceBeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource()); // 解析 @Transactionaladvisor.setAdvice(transactionInterceptor()); // 设置拦截器advisor.setOrder(platformTransactionManager.getOrder());return advisor;}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionInterceptor transactionInterceptor() {// 创建事务拦截器TransactionInterceptor interceptor = new TransactionInterceptor();interceptor.setTransactionAttributeSource(transactionAttributeSource());interceptor.setTransactionManager(transactionManager());return interceptor;}
}
关键点:
TransactionInterceptor
是MethodInterceptor
,负责拦截方法调用。BeanFactoryTransactionAttributeSourceAdvisor
是Advisor
,包含:
- Pointcut:匹配所有标注
@Transactional
的方法。- Advice:即
TransactionInterceptor
。
三、代理创建阶段:AbstractAutoProxyCreator
当一个 Bean(如 UserService
)被创建并初始化后,InfrastructureAdvisorAutoProxyCreator
会执行:
// AbstractAutoProxyCreator.java
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {// 1. 获取所有匹配的 Advisor(包括事务 Advisor)List<Advisor> advisors = findEligibleAdvisors(bean.getClass(), beanName);// 2. 如果有匹配的 Advisor,则创建代理if (!advisors.isEmpty()) {return createProxy(bean, beanName, advisors);}return bean;
}
- 如果
UserService
类或方法上有@Transactional
,BeanFactoryTransactionAttributeSourceAdvisor
会被匹配。 - Spring 使用 JDK 动态代理(实现接口)或 CGLIB(继承类)创建代理对象。
四、方法调用阶段:AOP 拦截与事务逻辑
当你调用 userService.saveUser()
时,实际调用的是 代理对象。
1. 代理触发 TransactionInterceptor.invoke()
// TransactionInterceptor.java
public Object invoke(MethodInvocation invocation) throws Throwable {// 调用父类 TransactionAspectSupport 的 invokeWithinTransactionreturn invokeWithinTransaction(invocation.getMethod(), invocation.getThis().getClass(),() -> invocation.proceed());
}
2. 核心:TransactionAspectSupport.invokeWithinTransaction
// TransactionAspectSupport.java
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,final InvocationCallback invocation) throws Throwable {// 1. 解析 @Transactional 注解,得到事务属性TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);// 2. 获取事务管理器PlatformTransactionManager tm = determineTransactionManager(txAttr);// 3. 开启事务TransactionStatus status = tm.getTransaction(txAttr);Object retVal;try {// 4. 执行目标方法(你的业务代码)retVal = invocation.proceed(); // 👈 真正执行 userService.saveUser()} catch (Throwable ex) {// 5. 异常:回滚completeTransactionAfterThrowing(txAttr, ex);throw ex;} finally {// 6. 清理事务信息cleanupTransactionInfo(txInfo);}// 7. 成功:提交commitTransactionAfterReturning(txAttr, status);return retVal;
}
invocation.proceed()
是 AOP 链式调用的关键,它会继续执行下一个拦截器,最终到达目标方法。
五、事务绑定到线程:TransactionSynchronizationManager
我们聚焦 tm.getTransaction(txAttr)
的内部实现。
1. AbstractPlatformTransactionManager.getTransaction()
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) {// 1. 获取事务对象(如 DataSourceTransactionManager 创建 ConnectionHolder)Object transaction = doGetTransaction();// 2. 判断当前线程是否已有事务if (isExistingTransaction(transaction)) {// 已有事务,根据传播行为处理(如 REQUIRED 加入,REQUIRES_NEW 挂起并新建)return handleExistingTransaction(...);}// 3. 没有事务,新建if (def.getPropagationBehavior() == PROPAGATION_REQUIRED) {return startTransaction(def, transaction, debug, suspendedResources);}
}
2. DataSourceTransactionManager.doBegin()
:绑定连接
protected void doBegin(Object transaction, TransactionDefinition definition) {Connection con = dataSource.getConnection();// 将连接包装为 ConnectionHolderDataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;txObject.setConnectionHolder(new ConnectionHolder(con), true);// 🌟 核心!绑定到 ThreadLocalTransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());// 标记当前线程有活跃事务TransactionSynchronizationManager.setActualTransactionActive(true);// 设置隔离级别、只读等TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(definition.getIsolationLevel());
}
3. TransactionSynchronizationManager.bindResource()
源码
private static final ThreadLocal<Map<Object, Object>> resources =new NamedThreadLocal<>("Transactional resources");public static void bindResource(Object key, Object value) throws IllegalStateException {Map<Object, Object> map = resources.get();if (map == null) {map = new HashMap<>();resources.set(map);}map.put(key, value);
}
关键点:数据库连接
Connection
被绑定到了当前线程的ThreadLocal<Map>
中,键是DataSource
。
六、DAO 层如何获取事务连接?
当你在 UserDao
中使用 JdbcTemplate
或 SqlSession
时:
jdbcTemplate.update("UPDATE users SET name = ? WHERE id = ?", "Tom", 1);
JdbcTemplate
内部会:
// JdbcTemplate.java
protected Connection getConnection() {// 从 TransactionSynchronizationManager 获取当前事务的连接return TransactionSynchronizationManager.getResource(dataSource);
}
因为前面
doBegin()
已经把连接 put 进去了,所以这里能拿到同一个连接,保证事务一致性。
七、自调用失效:AOP 视角
@Service
public class UserService {public void methodA() {methodB(); // ❌ this.methodB(),不是代理调用!}@Transactionalpublic void methodB() {// 业务代码}
}
执行流程:
外部调用 userService.methodA()
│
└─ 代理对象拦截 → TransactionInterceptor.invoke()│├─ 开启事务(如果 methodA 也有 @Transactional)│├─ 执行 methodA() 业务│ ││ └─ this.methodB() → JVM 直接调用 UserService.methodB()│ ││ └─ ❌ 没有经过代理 → TransactionInterceptor 不执行│ └─ @Transactional 完全被忽略!│└─ 提交/回滚事务
结论:只有通过代理对象调用的方法,才会触发
TransactionInterceptor
,@Transactional
才会生效。
八、图解:AOP + 事务全流程
[外部调用]↓
[代理对象] ←——— AOP 创建↓
TransactionInterceptor.invoke()↓
TransactionAspectSupport.invokeWithinTransaction()↓
AbstractPlatformTransactionManager.getTransaction()↓
DataSourceTransactionManager.doBegin()↓
TransactionSynchronizationManager.bindResource(connection) // ThreadLocal 绑定↓
invocation.proceed() → 执行目标方法↓
UserDao 使用 JdbcTemplate → 从 ThreadLocal 获取 connection↓
method 执行完成↓
commitTransactionAfterReturning() / completeTransactionAfterThrowing()↓
清理 ThreadLocal
总结
阶段 | 核心机制 |
---|---|
启动 | @EnableTransactionManagement 导入 TransactionInterceptor 和 Advisor |
代理创建 | BeanPostProcessor 为带 @Transactional 的 Bean 创建代理(JDK/CGLIB) |
方法调用 | 代理触发 TransactionInterceptor.invoke() |
事务开启 | TransactionAspectSupport.invokeWithinTransaction() 调用 getTransaction() |
线程绑定 | TransactionSynchronizationManager.bindResource() 使用 ThreadLocal 存储连接 |
DAO 访问 | JdbcTemplate 等从 ThreadLocal 获取当前事务连接 |
自调用失效 | this.method() 绕过代理,TransactionInterceptor 无法拦截 |
🔁 一句话总结:Spring 事务 = AOP 动态代理 +
TransactionInterceptor
拦截 +TransactionSynchronizationManager
的ThreadLocal
状态管理。
理解这三者如何协同工作,就真正掌握了 Spring 事务的“内核”。