Spring Batch依赖循环问题分析与非拆分类修复方案
解决Spring Batch依赖循环问题
测试Spring Batch时遇到依赖循环问题,无法定位根源。希望在不拆分类的前提下修复该问题。
配置类代码
package org.id.demo.test.dao; import org.springframework.batch.core.Job; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.core.step.tasklet.TaskletStep; import org.springframework.batch.item.ItemProcessor; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.LineMapper; import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; import org.springframework.batch.item.file.mapping.DefaultLineMapper; import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.Resource; import org.springframework.transaction.PlatformTransactionManager; @Configuration @EnableBatchProcessing public class SpringBatchConfig { @Autowired private JobRepository jobRepository; @Autowired private PlatformTransactionManager platformTransactionManager; @Autowired private ItemWriter<BankTransaction> bankTransactionItemWriter; @Autowired private ItemProcessor<BankTransaction, BankTransaction> bankTransactionItemProcessor; @Autowired private ItemReader<BankTransaction> flatFileItemReader; @Bean public Job bankJob() { TaskletStep step1 = new StepBuilder("step-load-data", jobRepository) .<BankTransaction, BankTransaction>chunk(100, platformTransactionManager) .reader(flatFileItemReader) .processor(bankTransactionItemProcessor) .writer(bankTransactionItemWriter) .build(); return new JobBuilder("ETL-job", jobRepository) .start(step1) .build(); } @Bean public FlatFileItemReader<BankTransaction> flatFileItemReader(@Value("${inputFile}") Resource inputFile) { FlatFileItemReader<BankTransaction> fileItemReader = new FlatFileItemReader<BankTransaction>(); fileItemReader.setName("just a reader name"); fileItemReader.setLinesToSkip(1); fileItemReader.setResource(inputFile); fileItemReader.setLineMapper(lineMapper()); return fileItemReader; } @Bean public LineMapper<BankTransaction> lineMapper() { DefaultLineMapper<BankTransaction> lineMapper = new DefaultLineMapper<>(); DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer(); lineTokenizer.setDelimiter(DelimitedLineTokenizer.DELIMITER_COMMA); lineTokenizer.setStrict(false); lineTokenizer.setNames("id", "accountID", "strTransactionDate", "transactionType", "amount"); lineMapper.setLineTokenizer(lineTokenizer); BeanWrapperFieldSetMapper<BankTransaction> fieldSetMapper = new BeanWrapperFieldSetMapper<>(); fieldSetMapper.setTargetType(BankTransaction.class); lineMapper.setFieldSetMapper(fieldSetMapper); return lineMapper; } }
报错信息
The dependencies of some of the beans in the application context form a cycle: jobRestController (field private org.springframework.batch.core.Job org.id.demo.test.dao.JobRestController.job) ┌─────┐ | springBatchConfig (field private org.springframework.batch.item.ItemReader org.id.demo.test.dao.SpringBatchConfig.flatFileItemReader) └─────┘
问题原因
Spring实例化SpringBatchConfig配置类时,需要先注入flatFileItemReader Bean,但flatFileItemReader本身由该配置类的@Bean方法创建。配置类的实例化依赖flatFileItemReader,而flatFileItemReader的创建又依赖配置类实例,形成循环依赖。
修复方案
移除配置类中对flatFileItemReader的@Autowired注入,直接在bankJob()方法中调用flatFileItemReader()方法获取Bean实例。Spring会对@Configuration类生成代理,调用@Bean方法时会返回容器中已存在的Bean(或触发创建),同时自动处理方法参数的依赖注入,避免循环依赖。
修改后的核心代码片段:
@Configuration @EnableBatchProcessing public class SpringBatchConfig { @Autowired private JobRepository jobRepository; @Autowired private PlatformTransactionManager platformTransactionManager; @Autowired private ItemWriter<BankTransaction> bankTransactionItemWriter; @Autowired private ItemProcessor<BankTransaction, BankTransaction> bankTransactionItemProcessor; // 移除此处的@Autowired注入 // @Autowired // private ItemReader<BankTransaction> flatFileItemReader; @Bean public Job bankJob() { TaskletStep step1 = new StepBuilder("step-load-data", jobRepository) .<BankTransaction, BankTransaction>chunk(100, platformTransactionManager) // 直接调用@Bean方法获取reader实例,Spring自动处理参数注入 .reader(flatFileItemReader()) .processor(bankTransactionItemProcessor) .writer(bankTransactionItemWriter) .build(); return new JobBuilder("ETL-job", jobRepository) .start(step1) .build(); } // 其余代码保持不变 }
内容的提问来源于stack exchange,提问作者kimo815
相关产品推荐
相关产品推荐

