You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Batch应用出现JobRestController与SpringBatchConfig循环依赖如何解决

问题原因

Spring Boot 2.6+ 版本默认禁用了循环依赖支持,你当前项目的依赖循环路径如下:

  • JobRestController 启动初始化时,需要注入 Job 实例
  • Job 是 SpringBatchConfig 配置类中通过 @Bean 方法声明的Bean,初始化Job前需要先完成SpringBatchConfig类的实例化
  • SpringBatchConfig 加了@AllArgsConstructor注解,需要通过构造函数注入ItemReader、ItemProcessor、ItemWriter三个Bean,而其中ItemReader的实现也是当前SpringBatchConfig类中声明的@Bean,必须等配置类实例化完成才能创建,二者形成初始化死锁,触发循环依赖报错。
解决方案

方案1(推荐:彻底消除循环)

修改SpringBatchConfig的写法,不要将依赖注入到配置类的成员变量中,改为将依赖声明为@Bean方法的入参,Spring会自动注入方法入参的Bean实例,修改后的代码参考:

import lombok.RequiredArgsConstructor;
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.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
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.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;

@Configuration
@EnableBatchProcessing
// 只注入两个工厂类即可,无需注入其他业务组件
@RequiredArgsConstructor
public class SpringBatchConfig {

    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;

    // 把Step依赖直接声明为方法入参
    @Bean
    public Job bankJob(Step stepLoadData) {
        return jobBuilderFactory.get("bank-data-loader-job")
                .start(stepLoadData)
                .build();
    }

    // 把批量处理组件直接声明为方法入参
    @Bean
    public Step stepLoadData(ItemReader<BankTransaction> bankTransactionItemReader,
                             ItemProcessor<BankTransaction, BankTransaction> bankTransactionItemProcessor,
                             ItemWriter<BankTransaction> bankTransactionItemWriter) {
        return stepBuilderFactory.get("step-load-data")
                .<BankTransaction, BankTransaction>chunk(100)
                .reader(bankTransactionItemReader)
                .processor(bankTransactionItemProcessor)
                .writer(bankTransactionItemWriter)
                .build();
    }

    @Bean
    public ItemReader<BankTransaction> flatFileItemReader(@Value("${inputFile}") Resource inputFile) {
        FlatFileItemReader<BankTransaction> flatFileItemReader = new FlatFileItemReader<>();
        flatFileItemReader.setName("CSV-READER");
        flatFileItemReader.setLinesToSkip(1);
        flatFileItemReader.setResource(inputFile);
        flatFileItemReader.setLineMapper(lineMapper());
        return flatFileItemReader;
    }

    @Bean
    public LineMapper<BankTransaction> lineMapper() {
        DefaultLineMapper<BankTransaction> lineMapper = new DefaultLineMapper<>();
        DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();
        lineTokenizer.setDelimiter(",");
        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;
    }
}

如果你的ItemProcessor和ItemWriter是在其他配置类中声明的,确保Bean类型匹配,或者添加@Qualifier指定Bean名称即可。

方案2(快速修复,不推荐)

直接在项目的application.properties配置文件中添加如下配置,开启循环依赖支持:

spring.main.allow-circular-references=true

方案3(临时修复)

在JobRestController中注入Job的位置添加@Lazy注解,延迟Job的初始化时机:

@RestController
@AllArgsConstructor
public class JobRestController {

    private JobLauncher jobLauncher;
    @Lazy
    private Job job;

    // 其余代码保持不变
}

内容的提问来源于stack exchange,提问作者Elhilali Yassine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 10:15:09