AfterReturningAdvice是在事务关闭前还是后执行?自定义通知事务顺序疑问
结论
你当前实现的自定义AfterReturningAdvice默认是在事务结束后执行的,但这个执行顺序不是固定的,完全由两个代理生成的先后逻辑决定。
原因说明
Spring的声明式事务本质也是通过AOP代理实现的,和你手动写的代理逻辑一样,都是在BeanPostProcessor的postProcessAfterInitialization阶段完成代理生成的:
- 负责生成事务代理的是Spring内置的
AnnotationAwareAspectJAutoProxyCreator,它默认的优先级为Ordered.LOWEST_PRECEDENCE(优先级数值越大,优先级越低) - 你自定义的
MethodBeanPostProcessor没有手动设置优先级的情况下,默认优先级同样是Ordered.LOWEST_PRECEDENCE,而Spring内置的BeanPostProcessor会早于自定义的同优先级BeanPostProcessor执行,所以事务代理会先生成,你的代理逻辑会把事务代理再包裹一层,外层代理的后置通知自然会在内层代理的逻辑全部执行完成(包括事务提交/回滚)后再运行,这也是你当前测试运行符合预期的原因。
如果想要主动控制顺序,只需要给你的MethodBeanPostProcessor实现Ordered接口或者添加@Order注解即可:
- 设置优先级比事务代理高(
@Order(Ordered.LOWEST_PRECEDENCE - 1)),你的代理会先生成,被事务代理包裹,此时你的AfterReturningAdvice就会在事务提交前执行 - 设置优先级和事务代理一致,利用内置处理器先注册的规则,你的逻辑就固定在事务结束后执行
如果要完全确保逻辑在事务提交后才执行,更稳妥的方式是直接用Spring提供的@TransactionalEventListener,指定phase = TransactionPhase.AFTER_COMMIT,不用依赖代理顺序的隐式规则。
官方文档参考说明
对应的规则可以在Spring官方文档的两个部分找到:
- AOP模块的「通知排序(Advice Ordering)」章节:明确了多个切面作用于同一个连接点时,优先级越高的切面前置通知越先执行,后置通知越晚执行
- 事务管理模块的「声明式事务代理机制」章节:明确了
@Transactional对应的切面默认优先级为Ordered.LOWEST_PRECEDENCE,可通过@EnableTransactionManagement的order属性修改
内容的提问来源于stack exchange,提问作者Karord
相关产品推荐
相关产品推荐

