在Spring Batch中调用ItemReader,ItemProcessor,ItemWriter的构造函数时?

时间:2014-03-07 15:57:09

标签: java spring-batch

我想知道这样的流程:

ItemReader -> ItemProcessor -> ItemWriter 

其中每个都是实现等效接口的自定义类,并且在面向块的步骤中,何时将调用每个构造函数?

到目前为止我理解(如果我错了,请纠正我),ItemWriter构造函数将在步骤开始时调用一次,对于每个chunk,write()将仅被调用。此规则适用于其他2?

2 个答案:

答案 0 :(得分:2)

Vinay的回答是正确的,但需要一些细化。

对于reader-processor-> writer Spring调用默认构造函数(让我们忽略@PostConstruct等) 范围(“步骤”),顾名思义是为每一步创建一个新bean。 步骤不必与线程一对一,例如,假设我有以下读取器 - 处理器 - >编写器

  @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>

构造函数将被调用两次,以便读取器 - >处理器 - >编写器
日志将是

 [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

所以在这种情况下我们应该小心考虑我们正在分享同一位作家。

答案 1 :(得分:1)

ItemWriter,Reader和Writer都是Spring bean。如果您使用@component标记它们,则所有这些都只创建一次,并在创建ApplicationContext时调用构造函数。虽然您可以指定不同的范围,例如@scope("step")。这将使每个线程在多线程批处理中都有自己的组件