【发布时间】:2014-03-07 15:57:08
【问题描述】:
我想知道这样的流程:
ItemReader -> ItemProcessor -> ItemWriter
其中每一个都是实现等效接口并在面向块的步骤中的自定义类,何时调用每个构造函数?
据我所知(如果我错了,请纠正我) ItemWriter 构造函数将在步骤开始时调用一次,并且对于每个块,只会调用 write() 。此规则适用于其他 2 个?
【问题讨论】:
标签: java spring-batch
我想知道这样的流程:
ItemReader -> ItemProcessor -> ItemWriter
其中每一个都是实现等效接口并在面向块的步骤中的自定义类,何时调用每个构造函数?
据我所知(如果我错了,请纠正我) ItemWriter 构造函数将在步骤开始时调用一次,并且对于每个块,只会调用 write() 。此规则适用于其他 2 个?
【问题讨论】:
标签: java spring-batch
Vinay 的答案是正确的,但需要一些详细说明。
对于 reader-processor->writer,Spring 调用默认构造函数(让我们忽略 @PostConstruct 等) Scope(“step”),顾名思义就是为每一步创建一个新的bean。 步骤不必与线程是一对一的,例如假设我有以下 reader-processor->writer
@Component
@Scope("step")
public class DoNothingItemReader implements ItemReader<String>{
public DoNothingItemReader() {
LOGGER.info(String.format("New %s created"
,ClassUtils.getShortName(this.getClass())));
}
@Override
public String read() throws Exception{
LOGGER.info("Nothing to read...");
..
}
}
@Component
@Scope("step")
public class DoNothingItemProcessor implements ItemProcessor<String, String> {
public DoNothingItemProcessor() {
LOGGER.info(String.format("New %s created"
,ClassUtils.getShortName(this.getClass())));
}
@Override
public String process(String i) throws Exception {
LOGGER.info("Nothing to process...");
return i;
}
}
@Component
@Scope("step")
public class DoNothingItemWritter implements ItemWriter<String[]> {
public DoNothingItemWritter() {
LOGGER.info(String.format("New %s created"
,ClassUtils.getShortName(this.getClass())));
}
@Override
public void write(List<? extends String[]> items) throws Exception {
LOGGER.info("Nothing to write...");
}
现在我们分两步重复使用上面的内容,例如
<batch:job id="testScopStep">
<batch:step id="step1" next="step2">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="doNothingItemReader"
processor="doNothingItemProcessor"
writer="doNothingItemWritter" commit-interval="3">
</batch:chunk>
</batch:tasklet>
</batch:step>
<batch:step id="step2">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="doNothingItemReader"
processor="doNothingItemProcessor"
writer="doNothingItemWritter" commit-interval="3">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
构造函数将永远被调用两次 reader->processor->writer
日志将是
[SimpleJobLauncher] - <Job: [FlowJob: [name=testScopStep]] launched>
[SimpleStepHandler] - <Executing step: [step1]>
[DoNothingItemReader] - <New DoNothingItemReader created>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemProcessor] - <New DoNothingItemProcessor created>
[DoNothingItemProcessor] - <Nothing to process...>
[DoNothingItemProcessor] - <Nothing to process...>
[DoNothingItemWritter] - <New DoNothingItemWritter created>
[DoNothingItemWritter] - <Nothing to write...>
[SimpleStepHandler] - <Executing step: [step2]>
[DoNothingItemReader] - <New DoNothingItemReader created>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemProcessor] - <New DoNothingItemProcessor created>
[DoNothingItemProcessor] - <Nothing to process...>
[DoNothingItemProcessor] - <Nothing to process...>
[DoNothingItemWritter] - <New DoNothingItemWritter created>
[DoNothingItemWritter] - <Nothing to write...>
[SimpleJobLauncher] - <Job: [FlowJob: [name=testScopStep]] completed
现在在我们使用复合编写器时考虑以下场景
<batch:job id="testScopStep">
<batch:step id="step1">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="doNothingItemReader"
processor="doNothingItemProcessor"
writer="compositeWriter" commit-interval="3">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
这里的构造函数只会被调用一次。
日志会显示
[SimpleJobLauncher] - <Job: [FlowJob: [name=testScopStep]] launched>
[SimpleStepHandler] - <Executing step: [step1]>
[DoNothingItemReader] - <New DoNothingItemReader created>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemProcessor] - <New DoNothingItemProcessor created>
[DoNothingItemProcessor] - <Nothing to process...>
[DoNothingItemProcessor] - <Nothing to process...>
[DoNothingItemWritter] - <New DoNothingItemWritter created>
[DoNothingItemWritter] - <Nothing to write...>
[DoNothingItemWritter] - <Nothing to write...>
[SimpleJobLauncher] - <Job: [FlowJob: [name=testScopStep]] completed
所以在这种情况下,我们应该小心考虑到我们共享同一个作者。
【讨论】:
ItemWriter、Reader 和 Writer 都是 Spring bean。如果你用@component 标记了它们,那么它们都只创建一次,并且在你创建 ApplicationContext 时调用构造函数。尽管您可以指定不同的范围,例如@scope("step")。这将使每个线程在多线程批处理中都有自己的组件
【讨论】: