有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我正在尝试使用@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();
    }
}

我有一个类似的类,名为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.

但我认为这是模块化=真的全部要点。也就是说,处理名称冲突

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

@Autowired List<Job>只有一个作业(从Dummy2.class

如何正确配置这些作业


共 (1) 个答案

  1. # 1 楼答案

    @EnableBatchProcessing是一个Spring批处理注释,它早于Spring引导。因此,您需要考虑如何在Spring引导的上下文中工作。我看了一下你的申请表样本。让我先解释一下出了什么问题,然后再解释如何修复它

    问题

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

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

    解决方案

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

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

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

    还有许多其他方法可以移动类来防止Spring Boot的类路径扫描来拾取它们,只要Spring Boot不拾取Dummy1Dummy2,应用程序就应该像您所期望的那样工作。祝你好运