Spring modular=true 的批处理不适用于多个作业

Spring Batch with modular=true doesn't work for multiple jobs

我正在尝试使用 @EnableBatchProcessing(modular = true) 配置两个作业。据我所知,这是为了防止命名冲突。

这是我的作业配置:

@Configuration
public class Dummy1 {

    @Autowired
    JobBuilderFactory jobBuilderFactory;
    @Autowired
    StepBuilderFactory stepBuilderFactory;

    @Bean
    public Step step() {
        // < build step. Omitted for code clarity > 
    }

    @Bean
    public Job getJob() {
        return jobBuilderFactory.get("dummy-job-1")
                .start(step())
                .build();
    }
}

我有一个类似的 class 名为 Dummy2

我还定义了如下配置:

@Configuration
@EnableAutoConfiguration
@EnableBatchProcessing(modular = true)
public class BatchConfig {

    @Bean
    public ApplicationContextFactory getDummy1() {
        return new GenericApplicationContextFactory(Dummy1.class);
    }

    @Bean
    public ApplicationContextFactory getDummy2() {
        return new GenericApplicationContextFactory(Dummy2.class);
    }
}

当 运行 我收到的应用程序时:

The bean 'step', defined in class path resource [~PATH~/Dumm2.class], could not be registered. A bean with that name has already been defined in class path resource [~PATH~/Dumm1.class] and overriding is disabled.

但我认为这就是 modular=true 的全部意义。也就是说,处理名称冲突。

另一方面,如果我启用 bean 覆盖,我将剩下第二个作业覆盖第一个作业。

@Autowired List<Job> 只有一份工作(来自 Dummy2.class

如何正确配置这些作业?

@EnableBatchProcessing 是 Spring 早于 Spring Boot 的批注。因此,您需要考虑它是如何在 Spring Boot 的上下文中工作的。我查看了您的示例应用程序。让我先解释一下出了什么问题,然后我将解释如何修复它。

问题

当您配置 @EnableBatchProcessing(modular=true) 时,根据 javadoc,您在当前上下文中应该没有您不想被引导的 @Bean 定义。相反,您提供 ApplicationContextFactory 实现作为 @Bean,每个实现定义作业的子上下文。

但是,在您的应用程序中有一个问题。如前所述,@EnableBatchProcessing 早于 Spring Boot,因此您需要考虑它是如何在 Spring Boot 的上下文中工作的。在您的例子中,示例应用程序将所有 class 都放在同一个包中。默认情况下,Spring Boot 将对 @Configuration 注释的包中的 class 进行 class 路径扫描,您定义的 class 注释为 @SpringBootApplication 和 "below"。因此,在您的示例应用程序中,Spring Boot 会自动将 Dummy1Dummy2 引入应该是导致错误的父上下文中。

解决方案

要解决此问题,您需要阻止 Spring 引导将您的子上下文配置包含在其 class 路径扫描中。为了证明这一点,我通过将 Dummy1Dummy2 移动到包 com.example 来测试您的示例应用程序(一级 以上 class用 @SpringBootApplication 注释)。这阻止了 Spring Boot 通过其 class 路径扫描来拾取它们,并允许应用程序正确启动......还有两个其他小调整:

  1. 虽然 bean 名称可以在模块化配置中重复,但实际的作业名称不能。在 Dummy1Dummy2 中,您将两个作业名称都配置为 dummy-job-1。将一个更改为 dummy-job-2 即可解决此问题。
  2. Spring 启动需要批处理应用程序的数据源。我将 HSQLDB 添加到 POM 以证明我的修复成功了。

通过这些更改,您将能够构建您的应用程序并通过以下命令 运行 它:java -jar target/demo-0.0.1-SNAPSHOT.jar --spring.batch.job.names=dummy-job-1 to 运行 job 1 或 java -jar target/demo-0.0.1-SNAPSHOT.jar --spring.batch.job.names=dummy-job-2 to 运行 工作 2.

还有许多其他方法可以移动 classes 以防止 Spring Boot 的 classpath 扫描来拾取它们,只要 Spring Boot 不'选择 Dummy1Dummy2,该应用程序应按预期运行。祝你好运!