Spring 批量@JobScope bean 创建错误"A bean with that name has already been defined"

Spring Batch @JobScope bean creation error "A bean with that name has already been defined"

在我的Spring批处理项目中(Spring引导版本2.3。4.RELEASE,Java1.8),我有一个需要访问作业ID的处理器组件(用于跟踪目的)。我将 @JobScope 添加到 bean 声明中,这允许我访问作业 ID。

@Component("dealerItemProcessor")
@JobScope
public class DealerItemProcessor implements ItemProcessor<Dealer, Dealer> {    
   @Value("#{jobExecution}")
   private JobExecution jobExecution;
    
   @Override
   public Dealer process(final Dealer dealer) throws Exception {
      //Get jobExecution.getJobId(), process data bean
   }

我在 XML 中这样声明工作:

<job id="syncJob" >
    <step id="step1">
        <tasklet>
            <chunk reader="itemReader"
                   processor="dealerItemProcessor"
                   writer="itemWriter" commit-interval="1"/>
        </tasklet>
    </step>
    <listeners>
        <listener ref="syncJobCompletionNotificationListener"/>
    </listeners>
</job>

XML 配置加载为:

@Configuration
@EnableAutoConfiguration
@ImportResource("classpath:batch-job.xml")
public class XMLConfigurationLoader {
}

作业安排如下:

public SyncJobScheduler(@Qualifier("syncJob") Job dealerSyncJob,
                              JobLauncher jobLauncher) {
    this.syncJob = syncJob;
    this.jobLauncher = jobLauncher;
}
@Scheduled(cron = "0 0 */1 * * *")
public void schedule() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
   jobLauncher.run(syncJob, new JobParametersBuilder()
                .addDate("date", new Date())
                .toJobParameters());
}

当我在 Linux OS 服务器和 OpenJDK 1.8 中构建和 运行 项目时,出现以下错误。

***************************
APPLICATION FAILED TO START
***************************

Description:

The bean 'scopedTarget.dealerItemProcessor', defined in BeanDefinition defined in URL [jar:file:/var/www/jobs/upload-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/com/sync/connect/processor/DealerItemProcessor.class], could not be registered. A bean with that name has already been defined in URL [jar:file:/var/www/jobs/upload-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/com/sync/connect/processor/DealerItemProcessor.class] and overriding is disabled.

Action:

Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

我启用了调试模式,但看到了同样的错误。我该如何解决这个问题?可以指点一下吗?

更新 1: 我尝试将 JobScope 更改为 StepScope,并看到类似的异常。 2020-10-15 10:53:02.651 [调试] [主要]

[org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter:37] Application failed to start due to an exception
org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'scopedTarget.dealerItemProcessor' defined in BeanDefinition defined in URL [jar:file:/var/www/jobs/upload-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/com/sync/connect/processor/DealerItemProcessor.class]: Cannot register bean definition [Root bean: class [org.springframework.aop.scope.ScopedProxyFactoryBean]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in BeanDefinition defined in URL [jar:file:/var/www/jobs/upload-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/com/sync/connect/processor/DealerItemProcessor.class]] for bean 'scopedTarget.dealerItemProcessor': There is already [Generic bean: class [com.sync.connect.processor.DealerItemProcessor]; scope=step; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in URL [jar:file:/var/www/jobs/upload-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/com/sync/connect/processor/DealerItemProcessor.class]] bound.

您可以使用 @StepScope 而不是 @JobScope。您可以使用 stepExecution.getJobExecution() 来获取 jobExecution。然后你就像你提到的那样你可以获得jobId。

我通过实施 StepExecutionListener 使它起作用。这允许访问 StepExecution 对象,我们从中获取作业 ID。

@Component("dealerItemProcessor")
public class DealerItemProcessor implements ItemProcessor<Dealer, Dealer> , StepExecutionListener {
    
    private StepExecution stepExecution;

    @Override
    public Dealer process(final Dealer dealer) throws Exception {
    //get unique JobId like this - stepExecution.getJobExecutionId()
    // process logic
    }

    @Override
    public void beforeStep(StepExecution stepExecution) {
        //get the stepExecution Object.
        this.stepExecution = stepExecution;
    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        return null;
    }
}

此解决方案通过提供替代方案解决了获取 JobId 的需求。它没有解决问题中发布的Bean创建异常。