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 会自动将 Dummy1
和 Dummy2
引入应该是导致错误的父上下文中。
解决方案
要解决此问题,您需要阻止 Spring 引导将您的子上下文配置包含在其 class 路径扫描中。为了证明这一点,我通过将 Dummy1
和 Dummy2
移动到包 com.example
来测试您的示例应用程序(一级 以上 class用 @SpringBootApplication
注释)。这阻止了 Spring Boot 通过其 class 路径扫描来拾取它们,并允许应用程序正确启动......还有两个其他小调整:
- 虽然 bean 名称可以在模块化配置中重复,但实际的作业名称不能。在
Dummy1
和 Dummy2
中,您将两个作业名称都配置为 dummy-job-1
。将一个更改为 dummy-job-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 不'选择 Dummy1
和 Dummy2
,该应用程序应按预期运行。祝你好运!
我正在尝试使用 @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 会自动将 Dummy1
和 Dummy2
引入应该是导致错误的父上下文中。
解决方案
要解决此问题,您需要阻止 Spring 引导将您的子上下文配置包含在其 class 路径扫描中。为了证明这一点,我通过将 Dummy1
和 Dummy2
移动到包 com.example
来测试您的示例应用程序(一级 以上 class用 @SpringBootApplication
注释)。这阻止了 Spring Boot 通过其 class 路径扫描来拾取它们,并允许应用程序正确启动......还有两个其他小调整:
- 虽然 bean 名称可以在模块化配置中重复,但实际的作业名称不能。在
Dummy1
和Dummy2
中,您将两个作业名称都配置为dummy-job-1
。将一个更改为dummy-job-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 不'选择 Dummy1
和 Dummy2
,该应用程序应按预期运行。祝你好运!