企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## 一、原理 如果包含@Transactional注解,Spring会为这个bean动态地生成一个子类(即代理类,proxy),代理类是继承原来那个bean的;此时,当这个有注解的方法被调用的时候,实际上是由代理类来调用的,代理类在调用之前就会启动transaction。然而,如果这个有注解的方法是被同一个类中的其他方法调用的,那么该方法的调用并没有通过代理类,而是直接通过原来的那个bean,所以就不会启动transaction; 当Spring发现@Transactional或者@Async时,会自动生成一个ProxyObject,示意图如下: ![](https://img.kancloud.cn/27/bf/27bf571355ed4178801461fbeee3c9b4_998x518.png) ## 二、规则 ### **基本要点** @Transactional的作用域**是当前方法**,当前方法体内部执行出现符合规则的异常且没有被捕获,就会出现回滚; **只有异常传播抛出了标记了 @Transactional 注解的方法,事务才能回滚** ### **异常类型** 对于@Transactional可以保证RuntimeException(及其子类)及Error错误的回滚,如果想保证非RuntimeException异常也进行回滚,需要加上rollbackFor = Exception.class 参数; 例如: ``` @Transactional(rollbackFor = Exception.class) ``` 这样标识的方法,无论其代码执行中遇到什么异常,都会回滚; ### **异常不能捕获** 异常回滚,必须捕获到异常,一般来说,业务层不要捕获异常,而是抛出去,这样,业务层出现异常,就会回滚,否则,被处理掉的异常,是不可能触发事务回滚的; >[info] 简单来说,异常在方法内部被捕捉了,会导致@Transactional无效; ### **不能同类方法调用** 同一个类的不同方法,A方法没有@Transactional,B方法有@Transactional,则A调用B方法,事务不起作用; >[info] 比如说,如果需要做事务分解,把一个列表对象轮询业务整体事务拆分的时候,需要单独定义类和方法,再注入原Bean引用才可以; ### **公开且非final方法** 必须是public非final方法才可以支持事务; ### **非静态方法** 基于动态代理,故不得是静态方法; ### **多@Transactional调用** 1、无@Transactional方法,调用两个@Transactional事务方法,互不干扰; 2、如果@Transactiona方法继续调用@Transactional方法,则需要看propagation的定义;可以在一个事务方法中,调用另外一个@Transactional(propagation = Propagation.REQUIRES_NEW),计时在主事务中失败回滚,依然确保子事务正常提交; 实例: ``` @Component public class CheckRealName { @Autowired private CardInfoDao cardInfoDao; @Autowired private RayLocker rayLocker; @Transactional(propagation = Propagation.REQUIRES_NEW) public void doAction(CardInfo cardinfo) throws Exception { String lockKey = rayLocker.getUniqueKey(CardInfo.class, cardinfo.getCardId()); if (rayLocker.lock(lockKey)) { try { cardinfo.setRealNameStatus(ApiFacade.isRealNameCertified(cardinfo) ? CardRealNameStatus.real_named : CardRealNameStatus.not_real_named); cardInfoDao.save(cardinfo); } finally { rayLocker.unlock(lockKey); } } } } ``` CheckRealName.doAction可以被另外的@Transactional事务调用,并作为子事务; ### **异步任务事务** 参考:[后端框架/SprigBoot/核心技术/异步任务](../../%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1.md) ## 三、失效场景 ![](https://img.kancloud.cn/6d/da/6ddafcd87119094facb3c365034d0c96_1080x1071.png)