我正在从 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”)步骤作为类字段。然而,这个解决方案似乎比前一个解决方案更糟糕,因为否则我将步骤添加为类字段的动机为零,因为它们在我的类中只使用一次。
您能让我知道如何以更正确的方式修复我的批次吗?
替代解决方案:
@Bean("test")
public Job testJob()
{
return new JobBuilder("test", jobRepository).start(step1()).next(step2()).build();
}
为您的 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();
}