Spring Batch集成MongoDB配置解析失败:Bean定义冲突排查
问题
开发基于Spring Batch的功能,需求是读取Excel文件数据并写入MongoDB的students集合,计划通过API调用触发批处理任务。启动应用时始终报错:Failed to parse configuration class,配置代码如下:
package com.example.Study.Hall.Management.controller; import com.example.Study.Hall.Management.model.Student; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.launch.support.RunIdIncrementer; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.repository.support.MongoJobRepositoryFactoryBean; import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.item.ItemProcessor; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.data.MongoItemWriter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.MongoTransactionManager; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.transaction.PlatformTransactionManager; import java.io.FileInputStream; import java.io.IOException; import java.time.LocalDate; @Configuration @EnableBatchProcessing public class StudentBatchConfig { @Autowired private MongoTemplate mongoTemplate; @Bean public JobRepository jobRepository(MongoTemplate mongoTemplate) throws Exception { MongoJobRepositoryFactoryBean factory = new MongoJobRepositoryFactoryBean(); factory.setMongoOperations(mongoTemplate); return factory.getObject(); // Creates the JobRepository with MongoDB as the backend } @Bean public PlatformTransactionManager transactionManager(MongoTemplate mongoTemplate) { MongoDatabaseFactory mongoDatabaseFactory = mongoTemplate.getMongoDatabaseFactory(); return new MongoTransactionManager(mongoDatabaseFactory); // Provides transaction management for MongoDB } @Bean public Job importStudentJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) { return new JobBuilder("importStudentJob", jobRepository) .incrementer(new RunIdIncrementer()) // Optionally add a RunIdIncrementer for unique job instances .start(step1(jobRepository, transactionManager)) // Pass transaction manager to step1 .build(); } @Bean public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) { return new StepBuilder("step1", jobRepository) .<Student, Student>chunk(10, transactionManager) // Updated to include transaction manager .reader(excelReader()) .processor(processor()) .writer(writer()) .build(); } @Bean public ItemReader<Student> excelReader() { return new ItemReader<Student>() { private XSSFWorkbook workbook; private int currentRow = 0; @Override public Student read() throws Exception { if (workbook == null) { workbook = new XSSFWorkbook(new FileInputStream("C://Users//moham//Desktop//students.xlsx")); } Row row = workbook.getSheetAt(0).getRow(currentRow++); if (row == null) { workbook.close(); return null; // End of file } Student student = new Student(); student.setName(row.getCell(0).getStringCellValue()); student.setBloodGroup(row.getCell(1).getStringCellValue()); student.setDateOfBirth(LocalDate.from(row.getCell(2).getLocalDateTimeCellValue())); student.setPhoneNumber(row.getCell(3).getStringCellValue()); student.setExamPreparation(row.getCell(4).getStringCellValue()); return student; // Return the populated Student object. } }; } @Bean public ItemProcessor<Student, Student> processor() { return student -> { // You can add any processing logic here if needed. return student; // Return processed student object. }; } @Bean public ItemWriter<Student> writer() { MongoItemWriter<Student> writer = new MongoItemWriter<>(); writer.setTemplate(mongoTemplate); writer.setCollection("students"); return writer; } }
启动时的错误堆栈信息:
Error Failed to parse configuration class [com.example.Study.Hall.Management.StudyHallManagementApplication] at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:185) ~[spring-context-6.2.1.jar:6.2.1] at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:418) ~[spring-context-6.2.1.jar:6.2.1] at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:290) ~[spring-context-6.2.1.jar:6.2.1] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349) ~[spring-context-6.2.1.jar:6.2.1] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118) ~[spring-context-6.2.1.jar:6.2.1] at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:791) ~[spring-context-6.2.1.jar:6.2.1] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:609) ~[spring-context-6.2.1.jar:6.2.1] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.4.1.jar:3.4.1] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) ~[spring-boot-3.4.1.jar:3.4.1] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) ~[spring-boot-3.4.1.jar:3.4.1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) ~[spring-boot-3.4.1.jar:3.4.1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) ~[spring-boot-3.4.1.jar:3.4.1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) ~[spring-boot-3.4.1.jar:3.4.1] at com.example.Study.Hall.Management.StudyHallManagementApplication.main(StudyHallManagementApplication.java:14) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-3.4.1.jar:3.4.1] Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'studentBatchConfig' for bean class [com.example.Study.Hall.Management.controller.StudentBatchConfig] conflicts with existing, non-compatible bean definition of same name and class [com.example.Study.Hall.Management.configurations.StudentBatchConfig] at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:361) ~[spring-context-6.2.1.jar:6.2.1] at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:288) ~[spring-context-6.2.1.jar:6.2.1] at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:128) ~[spring-context-6.2.1.jar:6.2.1] at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:332) ~[spring-context-6.2.1.jar:6.2.1] at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:267) ~[spring-context-6.2.1.jar:6.2.1] at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:193) ~[spring-context-6.2.1.jar:6.2.1] at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:171) ~[spring-context-6.2.1.jar:6.2.1
根因是存在两个同名同类型的Bean:com.example.Study.Hall.Management.controller.StudentBatchConfig和com.example.Study.Hall.Management.configurations.StudentBatchConfig,导致Bean定义冲突,进而引发配置类解析失败。
解决方法
- 删除重复配置类:检查项目目录,直接删除其中一个
StudentBatchConfig类。通常配置类应放在configurations包下,建议删除controller包下的重复类,避免逻辑冗余。 - 指定唯一Bean名称:若必须保留两个类(不推荐),可通过
@Configuration注解的value属性给其中一个类指定唯一Bean名,避免冲突:@Configuration("controllerStudentBatchConfig") @EnableBatchProcessing public class StudentBatchConfig { // 原有代码不变 } - 调整组件扫描范围:修改启动类的
@ComponentScan注解,排除其中一个包的配置类扫描:@SpringBootApplication @ComponentScan(excludeFilters = @ComponentScan.Filter( type = FilterType.ASSIGNABLE_TYPE, classes = com.example.Study.Hall.Management.controller.StudentBatchConfig.class )) public class StudyHallManagementApplication { public static void main(String[] args) { SpringApplication.run(StudyHallManagementApplication.class, args); } }
内容的提问来源于stack exchange,提问作者mohammed fahimullah
相关产品推荐
相关产品推荐

