我正在尝试使用 @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.
但我认为这就是 modular=true 的全部意义。也就是说,处理名称冲突。
另一方面,如果我启用 bean 覆盖,我将剩下第二个作业覆盖第一个作业。
即@Autowired List<Job>
只有一份工作(来自 Dummy2.class
)
如何正确配置这些作业?
最佳答案
@EnableBatchProcessing
是早于 Spring Boot 的 Spring Batch 注解。因此,您需要考虑它在 Spring Boot 上下文中的工作方式。我查看了您的示例应用程序。让我先解释一下出了什么问题,然后再解释如何修复它。
问题
当你配置 @EnableBatchProcessing(modular=true)
,根据 javadoc,你应该没有 @Bean
当前上下文中您不想被引导的定义。相反,您提供 ApplicationContextFactory
实现为 @Bean
,其中每一个都定义了作业的子上下文。
但是,在您的应用程序中有一个问题。如前所述,@EnableBatchProcessing
早于 Spring Boot,因此您需要考虑它如何在 Spring Boot 的上下文中工作。在您的例子中,示例应用程序将所有类都放在同一个包中。默认情况下,Spring Boot 将对 @Configuration
进行类路径扫描。包中带注释的类,您定义的类用 @SpringBootApplication
注释和“下方”。因此,在您的示例应用程序中,Spring Boot 引入了 Dummy1
。和 Dummy2
自动进入导致错误的父上下文。
解决方案
要解决此问题,您需要防止 Spring Boot 在其类路径扫描中包含您的子上下文配置。为了证明这一点,我通过移动 Dummy1
测试了您的示例应用程序和 Dummy2
到包裹com.example
(一级 用 @SpringBootApplication
注释的类)。这阻止了 Spring Boot 通过其类路径扫描来拾取它们并允许应用程序正确启动......通过另外两个小调整:
- 虽然 bean 名称可以在模块化配置中重复,但实际的作业名称不能。在
Dummy1
和Dummy2
,您将两个作业名称都配置为dummy-job-1
.把一个改成dummy-job-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 不拾取 Dummy1
和 Dummy2
,该应用程序应按预期运行。祝你好运!
关于java - 带有 modular=true 的 Spring Batch 不适用于多个作业,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61370476/