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
的属性来决定是否创建新的事务。
DataSourceTransactionManager
的 commit
方法的实现如下:
“`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()
方法来提交事务。
DataSourceTransactionManager
的 rollback
方法的实现如下:
“`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
方法的执行流程如下:
- 获取事务属性,例如隔离级别、传播行为等。
- 获取事务管理器。
- 获取事务。
- 执行目标方法。
- 如果目标方法执行成功,则提交事务。
- 如果目标方法抛出异常,则回滚事务。
- 清理事务。
3. @Transactional
注解
@Transactional
注解是 Spring 声明式事务管理的核心。当 Spring 容器扫描到带有 @Transactional
注解的类或方法时,会自动为这些类或方法创建 AOP 代理,并在方法执行前后进行事务管理。
Spring 使用 TransactionAttributeSource
来解析 @Transactional
注解,获取事务属性。常见的 TransactionAttributeSource
实现包括:
AnnotationTransactionAttributeSource
: 从@Transactional
注解中获取事务属性。AttributesTransactionAttributeSource
: 从配置的属性文件中获取事务属性。
四、Spring 事务传播行为源码分析
Spring 事务传播行为的实现主要体现在 TransactionInterceptor
的 invokeWithinTransaction
方法中,它会根据 TransactionDefinition
中的 propagationBehavior
属性来决定如何处理事务。
例如,当 propagationBehavior
为 REQUIRED
时,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)
方法会创建一个新的事务。
当 propagationBehavior
为 REQUIRES_NEW
时,invokeWithinTransaction
方法的逻辑会更加复杂,它需要挂起当前事务,并创建一个新的事务。
五、总结
本文深入分析了 Spring 事务管理的架构和源码,从 PlatformTransactionManager
接口及其实现,到 TransactionInterceptor
类和 @Transactional
注解,都进行了详细的讲解。通过阅读本文,读者可以更好地理解 Spring 事务管理的实现原理,并能够更加灵活地使用 Spring 事务来保证数据的一致性和完整性。
Spring 的事务管理机制是一个复杂而精巧的系统,它充分利用了 AOP 和接口编程的思想,为开发者提供了一种简单而强大的事务管理方案。希望本文能够帮助读者更深入地理解 Spring 事务管理,并在实际开发中更好地应用它。
六、进阶学习建议
- 深入研究
TransactionSynchronizationManager
类,了解 Spring 如何管理线程相关的事务上下文。 - 了解 Spring 的事务隔离级别和并发问题的解决方案。
- 研究不同的
PlatformTransactionManager
实现,例如HibernateTransactionManager
和JpaTransactionManager
。 - 尝试自定义
TransactionAttributeSource
,以实现更灵活的事务属性配置。 - 阅读 Spring 官方文档,了解更多关于 Spring 事务管理的信息。
通过不断学习和实践,您将能够更加深入地理解 Spring 事务管理机制,并能够更加自信地应对各种复杂的事务场景。