当前版本仍在开发中,尚不被视为稳定版本。最新稳定版请使用 Spring Batch 文档 6.0.2!

从父 Step 继承

如果一组 Step 具有相似的配置,那么定义一个“父” Step,再让具体的 Step 从中继承属性,通常会很有帮助。这与 Java 中的类继承类似, “子” Step 会把自身的元素和属性与父 Step 的内容组合起来, 同时也可以覆盖父 Step 中的对应配置。

在下面的示例中,concreteStep1 这个 Step 继承自 parentStep。 最终实例化时,它会包含 itemReaderitemProcessoritemWriterstartLimit=5 以及 allowStartIfComplete=true。 另外,commitInterval 的值是 5,因为这个值被 concreteStep1 覆盖了,如下例所示:

<step id="parentStep">
    <tasklet allow-start-if-complete="true">
        <chunk reader="itemReader" writer="itemWriter" commit-interval="10"/>
    </tasklet>
</step>

<step id="concreteStep1" parent="parentStep">
    <tasklet start-limit="5">
        <chunk processor="itemProcessor" commit-interval="5"/>
    </tasklet>
</step>

即使是在 job 元素内部定义 step,id 属性依然是必需的,原因有两点:

  • id 会在持久化 StepExecution 时作为 step 名称使用。 如果同一个独立 step 在 job 中被多个 step 引用,就会发生错误。

  • 在创建作业流程时,正如本章后面将介绍的那样, next 属性应当引用流程中的 step,而不是独立定义的 step。

抽象 Step

有时你可能需要定义一个并不完整的父 Step 配置。 例如,如果某个 Step 配置里缺少 readerwritertasklet 属性, 初始化就会失败。如果父 step 必须在缺少这些属性中的一个或多个的情况下定义, 就应该使用 abstract 属性。一个 abstract Step 只会被继承,不会被实例化。

在下面的示例中,如果 abstractParentStep 没有被声明为抽象, 那么它就会尝试被实例化。子 StepconcreteStep2)则拥有 itemReaderitemWriter 以及 commit-interval=10

<step id="abstractParentStep" abstract="true">
    <tasklet>
        <chunk commit-interval="10"/>
    </tasklet>
</step>

<step id="concreteStep2" parent="abstractParentStep">
    <tasklet>
        <chunk reader="itemReader" writer="itemWriter"/>
    </tasklet>
</step>

合并列表

Step 上有些可配置元素本身就是列表,例如 <listeners/> 元素。 如果父 Step 和子 Step 都声明了 <listeners/>,那么默认情况下, 子 step 的列表会覆盖父 step 的列表。为了让子 step 能够在父 step 已定义的列表基础上继续追加监听器, 每个列表元素都带有一个 merge 属性。如果该元素指定 merge="true", 那么子 step 的列表就会与父 step 的列表合并,而不是覆盖它。

在下面的示例中,concreteStep3 这个 Step 最终会带有两个监听器: listenerOnelistenerTwo

<step id="listenersParentStep" abstract="true">
    <listeners>
        <listener ref="listenerOne"/>
    </listeners>
</step>

<step id="concreteStep3" parent="listenersParentStep">
    <tasklet>
        <chunk reader="itemReader" writer="itemWriter" commit-interval="5"/>
    </tasklet>
    <listeners merge="true">
        <listener ref="listenerTwo"/>
    </listeners>
</step>