我在之前的3篇文章里已经把AOP的底层以及重点说清楚了,这里我们就来说一下也是基于AOP来实现的Spring事物
的问题,尽量一篇文章让你看懂它的来世今生.

1. Spring事物控制基础
首先,我们在MySQL里也接触过事务的概念,那事务是什么呢?简单点说就是一件事要不全部做完成功 ,要不然全部失败 ,那当然事务也是有ACID
这四个特征。原子性、一致性、隔离性、持久性
。
Spring提供了声明式事务管理,通过AOP和代理模式
来实现事务控制。Spring会为配置了事务的Bean创建一个代理对象,在方法调用前后插入事务逻辑。这里一般有2种配置,XML配置和注解配置。
2. Spring事物的一些高级特性
2.1 事物传播行为
我们首先要知道什么是事务传播,简单来说当一个事务在调用另一个事务的时候,如何处理事务的问题。
Spring定义了7种传播行为:
- REQUIRED:默认,当前存在事务则加入,否则新建。
- REQUIRES_NEW:始终新建事务,挂起当前事务(若有)。
- NESTED:在嵌套事务中执行(基于保存点)。
- SUPPORTS:存在事务则加入,否则非事务执行。
- NOT_SUPPORTED:非事务执行,挂起当前事务(若有)。
- MANDATORY:必须存在事务,否则抛出异常。
- NEVER:必须非事务执行,否则抛出异常。
事物传播的源码在AbstractPlatformTransactionManager#handleExistingTransaction
里,我这里贴一种就行,整体的逻辑一样:
scss
// 处理 PROPAGATION_NOT_SUPPORTED
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
// 挂起当前事务
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return newTransactionStatus(null, false, newSynchronization, ...);
}
2.2 事物的隔离级别与回滚规则
Spring支持数据库的四种隔离级别,读未提交、读已提交、不可重复读、串行执行。
而Spring的回滚规则有两种:
RuntimeException
和Error
触发回滚Checked Exception
不触发回滚
可通过@Transactional
的rollbackFor
和noRollbackFor
属性自定义回滚策略
3. Spring事物的底层实现
Spring事务管理的核心是TransactionInterceptor
和TransactionAspectSupport
类
3.1 TransactionInterceptor
TransactionInterceptor,我们看名字就知道它是一个拦截器,负责拦截方法,在方法调用前后处理事务。核心方法是 invoke
java
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
Method method = invocation.getMethod();
//执行事物逻辑
return invokeWithinTransaction(method, targetClass, invocation::proceed);
}
这里invokeWithinTransaction
是事务管理的关键方法,负责创建、提交、回滚事务。
3.2 TransactionAspectSupport
TransactionAspectSupport是事物执行的底层流程,在invokeWithinTrasaction
方法中整个流程是: 解析注解或者XML
->根据你定义的传播行为决定是否开启新事物
->执行目标方法
->捕获异常并根据定义的规则进行回滚
->提交事物
scss
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, InvocationCallback invocation) throws Throwable {
// 获取事务属性
TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
// 获取事务管理器
PlatformTransactionManager tm = determineTransactionManager(txAttr);
// 创建事务
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, method.toString());
Object retVal;
try {
// 执行目标方法
retVal = invocation.proceedWithInvocation();
} catch (Throwable ex) {
// 异常时回滚
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
} finally {
cleanupTransactionInfo(txInfo);
}
// 提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
3.3 事物的创建、提交和回滚
这里分别的三个方法就是上面调用的三个方法:
- 创建:
createTransactionIfNecessary
根据事务属性和当前状态创建新事务或加入现有事务。 - 提交:
commitTransactionAfterReturning
在方法正常返回后提交事务。 - 回滚:
completeTransactionAfterThrowing
在异常时根据回滚规则决定是否回滚。
4. 示例
我们在使用的时候是这样的:
typescript
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public void createUser(String username) {
userRepository.save(new User(username));
if (username.equals("error")) {
throw new RuntimeException("User creation failed");
}
}
}
- 这里为
UserService
创建代理,拦截createUser
方法来进行调用。 - 上述的
TransactionInterceptor
根据@Transaction来创建事务。 - 执行createUser这个事务,保存用户数据。
- 然后如果username为error的话就会抛出异常,不然就直接提交事务。
5. 总结与一些问题
事务失效:在某些情况下,事务会失效,有一些典型场景。
- 方法非public:@Transactional注解只用在public方法里
- 自调用问题:同一类中方法A调用方法B,B的事务注解失效
另外还有一些分布式事务,或者与锁结合也是面试中会问到的。Spring 事务控制通过声明式管理,结合 AOP 和代理模式,简化了事务处理的复杂度。其核心实现依赖 TransactionInterceptor 和 TransactionAspectSupport,通过源码分析可以看出,Spring 在事务的创建、提交和回滚过程中提供了高度灵活性和可配置性。