一、Spring事务管理概述
在Java企业级开发中,Spring事务是保证数据一致性的核心机制。面试中,关于Spring事务的问题通常从基础概念出发,逐步深入到传播行为、隔离级别以及底层实现原理。Spring框架通过声明式事务管理,极大地简化了事务代码的开发,使得开发者只需关注业务逻辑,而无需处理繁琐的事务开启、提交和回滚操作。
Spring事务管理的核心接口是 PlatformTransactionManager,它定义了事务的基本操作。而 @Transactional 注解则是实现声明式事务的关键,它告诉Spring容器该方法需要事务支持。
二、Spring事务核心面试题解析
Q1: @Transactional 注解的工作原理是什么?
答案要点:
- ① Spring AOP:@Transactional 是基于AOP实现的。Spring容器在启动时会扫描带有该注解的Bean,并为其创建代理对象。
- ② 拦截器:当代理对象的方法被调用时,会经过
TransactionInterceptor拦截器。 - ③ 事务管理:拦截器根据配置获取事务管理器(PlatformTransactionManager),开启事务,执行目标方法,最后根据执行结果提交或回滚事务。
// 示例代码
@Service
public class OrderService {
@Transactional(rollbackFor = Exception.class)
public void createOrder(Order order) {
// 业务逻辑
orderMapper.insert(order);
// 如果发生异常,事务将回滚
}
}
Q2: 请解释Spring事务的七大传播行为?
答案要点:
| 传播行为 | 描述 | 场景示例 |
|---|---|---|
| REQUIRED | 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新事务。这是默认值。 | 大多数业务场景 |
| REQUIRES_NEW | 创建一个新事务,如果当前存在事务,则把当前事务挂起。 | 日志记录、独立操作 |
| SUPPORTS | 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。 | 查询操作 |
| NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,则把当前事务挂起。 | 耗时且不需要事务的操作 |
| MANDATORY | 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。 | 强制要求事务环境 |
| NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 | 绝对不能在事务中执行 |
| NESTED | 如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则创建一个新事务。 | 部分回滚场景 |
Q3: Spring事务的隔离级别有哪些?如何解决并发问题?
答案要点:
- ① READ_UNCOMMITTED:读未提交。允许读取未提交的数据,可能导致脏读、不可重复读、幻读。
- ② READ_COMMITTED:读已提交。防止脏读,但可能导致不可重复读和幻读。Oracle默认级别。
- ③ REPEATABLE_READ:可重复读。防止脏读和不可重复读,但可能导致幻读。MySQL默认级别。
- ④ SERIALIZABLE:串行化。最高级别,防止所有并发问题,但性能最低。
Spring默认的事务隔离级别是 DEFAULT,即使用数据库的默认隔离级别。
Q4: Spring事务失效的常见场景有哪些?
答案要点:
1. 方法非public
@Transactional 只能用于 public 方法上,否则事务不会生效。
2. 自调用问题
在同一个类中,A方法调用B方法,B方法的 @Transactional 不会生效。因为AOP代理的是Bean本身,自调用绕过代理对象。
3. 异常被捕获
如果方法内部 try-catch 捕获了异常,且未抛出,事务不会回滚。应使用 rollbackFor 指定回滚异常类型。
4. 数据库引擎不支持
只有 InnoDB 等支持事务的引擎才有效,MyISAM 不支持事务。
三、Spring事务源码深度解析
理解Spring事务的源码有助于解决复杂问题。核心流程如下:
- ① 代理创建:在Spring容器初始化时,
AnnotationTransactionAttributeSource解析@Transactional注解,生成事务属性。 - ② 拦截执行:
TransactionInterceptor拦截方法调用,获取事务属性,调用TransactionManager。 - ③ 事务开启:
AbstractPlatformTransactionManager根据传播行为决定是开启新事务还是加入现有事务。 - ④ 资源绑定:通过
TransactionSynchronizationManager将Connection与当前线程绑定,确保同一事务中使用的Connection是同一个。 - ⑤ 提交/回滚:方法执行完毕后,根据异常情况和rollbackFor配置,决定提交或回滚事务。
四、总结与建议
掌握Spring事务是Java后端开发的必备技能。面试中,建议从基础注解入手,逐步深入到传播机制和隔离级别,最后结合源码理解其实现原理。同时,要特别注意事务失效的场景,这是实战中最容易遇到的问题。
对于高级开发者,还需要了解分布式事务、动态数据源等高级主题,以应对更复杂的业务场景。