Spring Batch集成Spring Cloud Starter Task调用stop报事务管理器冲突如何解决
你遇到的报错是因为Spring Batch的JobOperator执行任务停止逻辑时,需要依赖TransactionManager完成事务操作,而你的工程中同时存在两个同类型的事务管理器Bean:业务默认注入的transactionManager、Spring Cloud Task自动配置注入的springCloudTransactionManager,Spring无法确定要选择哪个实例完成注入。
报错原文:
org.springframework.beans.factory.NoUniqueBeanDefinationException: No qualifying bean of type 'org.springframework.transaction.TransactionManager' available: expected single matching bean but found 2: transactionManager, springCloudTransactionManager
方案1:显式指定Spring Batch使用的事务管理器(推荐)
在Spring Batch的配置类的@EnableBatchProcessing注解上,增加transactionManagerRef参数,直接指定Batch组件统一使用的事务管理器即可:
// 通常指定你业务默认使用的transactionManager即可 @EnableBatchProcessing(transactionManagerRef = "transactionManager") @Configuration public class SpringBatchConfig { // 其他Batch相关配置逻辑 }
这个方案只会影响Spring Batch组件的事务管理器选择,不会干扰其他模块的事务逻辑,适配远程分区场景的兼容性最好。
方案2:标记默认事务管理器为全局优先
如果你不想修改Batch的配置,可在你业务常用的事务管理器Bean定义上增加@Primary注解,Spring遇到同类型多Bean时会优先使用带@Primary标记的实例:
@Bean @Primary public TransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); }
注意这个方案会全局影响所有TransactionManager的依赖注入点,如果你有业务场景需要明确区分使用两个事务管理器,不要使用该方案。
方案3:手动配置JobOperator指定事务管理器
如果你需要单独给JobOperator自定义事务管理器,可以手动注册JobOperator实例,显式注入指定的事务管理器:
@Bean public JobOperator jobOperator( JobExplorer jobExplorer, JobRepository jobRepository, JobRegistry jobRegistry, // 用@Qualifier指定你需要的事务管理器 @Qualifier("transactionManager") TransactionManager transactionManager ) { SimpleJobOperator operator = new SimpleJobOperator(); operator.setJobExplorer(jobExplorer); operator.setJobRepository(jobRepository); operator.setJobRegistry(jobRegistry); operator.setTransactionManager(transactionManager); return operator; }
内容的提问来源于stack exchange,提问作者dave

