NoUniqueBeanDefinitionException:预期有单个匹配 bean,但发现了 2 个

问题描述 投票:0回答:2

我正在从 spring-batch 3(JDK11、j2ee)迁移到版本 5.1.1(JDK 17、Jakarta)。

我的工作有两个步骤。每个步骤都在具有 @Bean 注释的方法中定义。然后,这些步骤被传递到定义实际作业的方法,该方法也是 @Bean 注释的,将步骤作为方法参数传递。

这是我的代码的样子:

@ComponentScan({ "this.class.package" })
public class TestJob
    extends
    CommonBatchConfig
{
    @Autowired
    JobRepository jobRepository;

    @Bean("test")
    public Job testJob(Step step1, Step step2)
    {
        return new JobBuilder("test", jobRepository).start(step1).next(step2).build();
    }

    @Bean
    public Step step1(ItemReader reader, JpaTransactionManager transactionManager,
        ItamWriter writer, Listener listener)
    {
        return new StepBuilder("step1", jobRepository)
            .chunk(50, transactionManager)
            .reader(reader)
            .writer(writer).transactionManager(transactionManager).listener(listener)
            .build();
    }

    @Bean
    public Step step2(Tasklet tasklet, JpaTransactionManager transactionManager,
        Listener listener)
    {
        return new StepBuilder("step2", jobRepository).tasklet(tasklet, transactionManager)
            .listener(listener).build();
    }

}

我在执行过程中遇到的错误是:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.batch.core.Step' available: expected single matching bean but found 2: step1,step2

解决方法是向 testJob 方法中的参数添加 @Qualifier 注释。固定方法如下:

    @Bean("test")
    public Job testJob(@Qualifier("step1") Step step1, @Qualifier("step2") Step step2)
    {
        return new JobBuilder("test", jobRepository).start(step1).next(step2).build();
    }

但是,我不喜欢这个解决方案,因为它迫使我重复参数名称两次。在我看来,解决方案是按名称而不是仅按类型执行 bean 解析,就像这里的情况一样。

另一个解决方案似乎将自动装配(“@Autowired”)步骤作为类字段。然而,这个解决方案似乎比前一个解决方案更糟糕,因为否则我将步骤添加为类字段的动机为零,因为它们在我的类中只使用一次。

您能让我知道如何以更正确的方式修复我的批次吗?

java spring spring-batch
2个回答
0
投票

替代解决方案:

@Bean("test")
public Job testJob()
{
     return new JobBuilder("test", jobRepository).start(step1()).next(step2()).build();
}

0
投票

为您的 Step beans 命名,然后在作业定义中使用 @Qualifier 注释可能会解决您的问题。这样您的步骤名称就不会出现歧义。 比如:

    @Bean("test")
    public Job testJob(@Qualifier("step1") Step step1, @Qualifier("step2") Step step2)
    {
        return new JobBuilder("test", jobRepository).start(step1).next(step2).build();
    }

    @Bean(name = "step1")
    public Step step1(ItemReader reader, JpaTransactionManager transactionManager,
        ItamWriter writer, Listener listener)
    {
        return new StepBuilder("step1", jobRepository)
            .chunk(50, transactionManager)
            .reader(reader)
            .writer(writer).transactionManager(transactionManager).listener(listener)
            .build();
    }

    @Bean(name = "step2")
    public Step step2(Tasklet tasklet, JpaTransactionManager transactionManager,
        Listener listener)
    {
        return new StepBuilder("step2", jobRepository).tasklet(tasklet, transactionManager)
            .listener(listener).build();
    }
© www.soinside.com 2019 - 2024. All rights reserved.