Spring @Transactional注解失效排查:手动注入事务Bean可正常运行
首先咱们聚焦你遇到的核心问题:标注了@Transactional("transactionManager")的Service类事务完全不生效,但手动创建事务Bean注入时功能正常。结合你贴出的代码,我整理了几个最可能的原因和对应的解决方案:
1. 组件扫描范围未覆盖Service类
你怀疑包路径的问题非常准确——如果你的FulfillmentRequestManager和RequestFulfillmentService所在的包没有被Spring的组件扫描机制覆盖,这些类根本不会被Spring容器管理,@Transactional注解自然会被直接忽略。
检查与修复:
- 确认你的配置类(
DatabaseConfig)或者Spring Boot主启动类上是否添加了@ComponentScan注解,并且指定的basePackages包含Service类所在的包路径。比如:@ComponentScan(basePackages = {"com.yourproject.services", "com.yourproject.config"}) - 如果是Spring Boot项目,主启动类默认会扫描自身所在包及子包,所以要确保Service类在主启动类的包层级范围内。
2. 事务管理器配置存在实例重复创建的问题
看你DatabaseConfig里的transactionManager()方法,直接调用了fmsEntityManagerFactory()来获取实例:
@Bean public PlatformTransactionManager transactionManager() { JpaTransactionManager transactionManager = new JpaTransactionManager(); LocalContainerEntityManagerFactoryBean entityManagerFactory = fmsEntityManagerFactory(); transactionManager.setEntityManagerFactory(entityManagerFactory.getObject()); transactionManager.setDataSource(entityManagerFactory.getDataSource()); return transactionManager; }
这里有个关键坑:在@Bean方法内部直接调用另一个@Bean方法,不会触发Spring的Bean代理逻辑,会每次创建一个全新的实例。这就导致事务管理器绑定的EntityManagerFactory,和你业务代码中实际使用的EntityManagerFactory不是同一个实例,事务自然无法生效。
修复方案:
通过依赖注入的方式获取EntityManagerFactory和DataSource,而非直接调用@Bean方法:
@Bean public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory, DataSource dataSource) { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(entityManagerFactory); transactionManager.setDataSource(dataSource); return transactionManager; }
这样Spring会自动注入容器中已经初始化好的单例实例,保证事务管理器和业务逻辑使用的是同一套资源。
3. 事务代理模式不匹配
Spring的@EnableTransactionManagement默认使用JDK动态代理,这种代理方式要求被代理类必须实现接口。如果你的Service类(比如FulfillmentRequestManager)没有实现任何接口,动态代理会直接失效,@Transactional注解也不会被处理。
检查与修复:
- 给Service类添加对应的接口,比如让
FulfillmentRequestManager实现FulfillmentRequestManagerInterface,并且依赖注入时使用接口类型; - 或者修改
@EnableTransactionManagement的代理模式为CGLIB代理:
这样即使类没有实现接口,Spring也会通过生成子类代理的方式来处理事务注解。@EnableTransactionManagement(proxyTargetClass = true)
4. 确认@Transactional注解的属性是否正确
你使用@Transactional("transactionManager")指定了事务管理器名称,要确认你的事务管理器Bean名称确实是transactionManager——因为你的@Bean方法名是transactionManager,默认名称是正确的,但如果存在多个事务管理器,要确保名称完全匹配。另外也可以尝试不指定名称,让Spring自动匹配(当容器中只有一个事务管理器时)。
额外验证步骤
- 开启Spring事务的调试日志,添加以下配置:
这样可以在日志中清晰看到事务的创建、提交/回滚过程,帮助快速定位问题;logging.level.org.springframework.transaction=DEBUG logging.level.org.springframework.orm.jpa=DEBUG - 检查Service类是否被Spring代理:在Service方法中打印
this.getClass().getName(),如果输出的是类似com.yourproject.service.FulfillmentRequestManager$$EnhancerBySpringCGLIB$$xxxx的类名,说明代理生效;如果是原类名,说明代理未生成,事务自然失效。
内容的提问来源于stack exchange,提问作者Kiran HG

