面试记录 2026-10-11
题目:Spring中如何开启事务?
难度:medium
标签:spring/transaction, difficulty/medium
评分:⭐⭐⭐⭐☆(4/5)
我的回答
Spring 启动事务主要有两种方式。一个是通过 XML 进行配置,另外一个是通过注解进行配置。首先需要配置开启事务支持的注解,通过 Configer 配置注入进去。At,具体的注解是 at Enable Configer Transaction 还是什么,具体不记得了。然后在对应的使用的方法上增加 @Transactional 注解,这样对应的方法就开启了事务。另外,启动事务需要有相关的前置支持。首先第一点,对应的方法需要是一个公共的方法,并且当前调用是通过代理调用的,而不是在当前的 class 内部进行调用。因为事务是依赖 Spring 提供的代理来实现的。另外,Spring 的事务虽然是通过代理实现的,但代理也是基于数据库的事务支持才能实现的,所以另一重要条件是需要事务支持。
点评
优点:
- 核心两种方式说对了:XML 配置和注解配置
- 提到了 @EnableTransactionManagement 和 @Transactional(虽然术语有点混乱)
- 提到了事务失效的常见原因:public 方法、代理调用、自调用问题
- 提到了需要数据库事务支持(JDBC 事务)
不足:
- 术语混乱:"At Enable Configer Transaction" 应该是 @EnableTransactionManagement
- 漏掉了事务传播行为(Propagation)和隔离级别(Isolation)
- 漏掉了 @Transactional 的属性配置(readOnly、timeout、propagation、isolation)
- 漏掉了自调用问题的具体解决方案(AopContext.currentProxy() 或代理注入)
补充:
- @EnableTransactionManagement 开启事务支持(JavaConfig)或 <tx:annotation-driven/>(XML)
- @Transactional 常用属性:readOnly、timeout、propagation、isolation、rollbackFor
- 事务传播行为:REQUIRED(默认)、REQUIRES_NEW、SUPPORTS、NOT_SUPPORTED 等 7 种
- 事务隔离级别:READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE 等
- 自调用解决方案:通过 AopContext.currentProxy() 获取代理对象,或注入代理对象
完整讲解
第一部分:知识重点剖析
核心考点定位:考察 Spring 声明式事务的配置方式和失效场景,理解事务的底层实现机制。
知识点拆解:
- 开启事务的两种方式:
- XML 配置:
<tx:annotation-driven/> + <tx:advice> 定义事务属性
- 注解配置:
@EnableTransactionManagement + @Transactional
- @Transactional 常用属性:
readOnly:是否只读(优化性能)
timeout:超时时间(秒)
propagation:传播行为(7 种)
isolation:隔离级别(4 种)
rollbackFor:指定异常类型回滚
- 事务传播行为(7 种):
- REQUIRED(默认):有事务就加入,没事务就创建
- REQUIRES_NEW:总是新建事务,当前事务挂起
- SUPPORTS:有事务就加入,没事务就非事务执行
- NOT_SUPPORTED:非事务执行,当前事务挂起
- MANDATORY:必须在事务中,否则抛异常
- REQUIRES:同 REQUIRED
- NESTED:嵌套事务
- 事务隔离级别(4 种):
- READ_UNCOMMITTED:读未提交(最低,可能有脏读)
- READ_COMMITTED:读已提交(默认)
- REPEATABLE_READ:可重复读(MySQL 默认)
- SERIALIZABLE:串行化(最高,性能最差)
- 事务失效的常见场景:
- 方法不是 public
- 自调用(同一个类内部调用)
- 没有数据库事务支持
- 异常被捕获未抛出
- 不是 Spring 管理的 Bean
- 数据库引擎不支持事务(如 MyISAM)
第二部分:考察方向与延伸递进
考察方向:
- 深度:理解事务的底层实现(AOP 代理 + 数据库事务)
- 广度:关联事务传播行为、隔离级别、失效场景
- 应用:能诊断事务失效问题,能根据场景选择合适的事务配置
延伸递进面试题:
- @Transactional 有哪些常用属性?分别是什么作用?
- 解答要点:readOnly、timeout、propagation、isolation、rollbackFor
- 事务传播行为有哪些?REQUIRED 和 REQUIRES_NEW 有什么区别?
- 解答要点:REQUIRED 有事务就加入,REQUIRES_NEW 总是新建事务
- 自调用为什么会导致事务失效?怎么解决?
- 解答要点:自调用不走代理,通过 AopContext.currentProxy() 或代理注入解决
第三部分:面试者参考回答(三步法口语化,300-400 字)
【一句话结论】
面试官您好,Spring 开启事务主要有两种方式:XML 配置和注解配置,注解方式更常用。
【三点展开】
第一,配置方式有两种。XML 方式用 <tx:annotation-driven/>,注解方式用 @EnableTransactionManagement 开启事务支持,然后在方法上标注 @Transactional。
第二,@Transactional 常用属性包括 readOnly(只读优化)、timeout(超时时间)、propagation(传播行为)、isolation(隔离级别)、rollbackFor(指定异常回滚)。
第三,事务失效的常见场景有:方法不是 public、自调用(同一个类内部调用)、异常被捕获未抛出、不是 Spring 管理的 Bean。自调用是因为不走代理,可以通过 AopContext.currentProxy() 或代理注入解决。
【一句边界】
当然,Spring 事务是基于 AOP 代理和数据库事务实现的,如果数据库引擎不支持事务(如 MyISAM),事务也会失效。