Spring中ServiceLocatorFactoryBean事务传递及回滚问题咨询
Spring中ServiceLocatorFactoryBean的事务传递与问题解决
一、已开启的事务能传递给工厂创建的服务吗?
当然可以!但得满足两个关键前提:
- 你通过
ServiceLocatorFactoryBean获取的目标服务,本身已经标注了@Transactional注解,并且Spring的事务代理机制(JDK动态代理或CGLIB)能正常生效。 - 事务的传播属性配置合理(比如默认的
REQUIRED就会自动加入当前已有的事务)。
这个工厂本质就是个Spring容器的bean定位器,它帮你拿到的还是容器里的代理对象,只要代理没问题,事务上下文就能正常传递。
二、ServiceLocatorFactoryBean怎么管理事务?
敲黑板:这个工厂本身不负责事务管理!它的核心功能只是提供统一的接口来获取容器中的bean,事务逻辑完全由Spring的事务框架(比如PlatformTransactionManager)来处理,和普通Spring bean的事务流程一模一样:
- 当你通过工厂获取服务时,如果拿到的是事务代理对象,方法调用就会触发Spring的事务拦截器,自动处理事务的开启、传播、提交或回滚。
- 如果目标服务没被事务代理(比如漏加
@Transactional,或者代理没生效),那自然不会有任何事务控制逻辑。
三、受检异常抛出后事务不回滚的问题解决
这其实是Spring事务的默认规则在搞事情:默认情况下,Spring只对RuntimeException(运行时异常)和Error触发事务回滚,受检异常(比如自定义的业务受检异常、SQLException这类)不会自动触发回滚。
给你两个直接的解决办法:
- 在
@Transactional注解里明确指定要回滚的受检异常类型:// 只针对你的自定义受检异常回滚 @Transactional(propagation = Propagation.REQUIRED, rollbackFor = YourBusinessCheckedException.class) // 或者对所有异常都回滚(包括受检异常) @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) - 手动触发事务回滚:如果不想修改注解,可以在抛出异常前手动标记事务为回滚状态:
// 在方法内部调用这个方法,强制事务回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
另外还要排查几个常见坑:
- 检查通过工厂获取的服务是不是真的是事务代理对象:打印实例的Class名称,如果是代理类,会包含
$Proxy(JDK代理)或者CGLIB相关的字样。如果不是,说明事务代理没生效,得检查Spring的组件扫描、代理配置是不是正确。 - 确认事务传播属性:比如如果用了
Propagation.NOT_SUPPORTED(不支持事务)或者Propagation.REQUIRES_NEW(开启新事务),会导致和外部事务脱离,回滚逻辑自然不会影响外部事务。 - 有没有提前提交事务:比如在try块里调用了某些会触发事务提交的操作(比如手动调用commit,或者某些框架的自动提交逻辑),导致异常抛出时事务已经提交了。
内容的提问来源于stack exchange,提问作者Vlada
相关产品推荐
相关产品推荐

