【问题标题】:When constructors for ItemReader, ItemProcessor, ItemWriter are called in Spring Batch?在 Spring Batch 中何时调用 ItemReader、ItemProcessor、ItemWriter 的构造函数?
【发布时间】:2014-03-07 15:57:08
【问题描述】:

我想知道这样的流程:

ItemReader -> ItemProcessor -> ItemWriter 

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

据我所知(如果我错了,请纠正我) ItemWriter 构造函数将在步骤开始时调用一次,并且对于每个块,只会调用 write() 。此规则适用于其他 2 个?

【问题讨论】:

    标签: java spring-batch


    【解决方案1】:

    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
    

    所以在这种情况下,我们应该小心考虑到我们共享同一个作者。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-08-02
        • 1970-01-01
        • 2021-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-31
        相关资源
        最近更新 更多