继承自父 `步骤`

如果一组 `步骤` 共享相似的配置,那么定义一个“父” `步骤`,具体的 `步骤` 可以从其继承属性,可能会有所帮助。类似于 Java 中的类继承,“子” `步骤` 将其元素和属性与父步骤结合。子步骤也会覆盖父步骤中的任何设置。

在下面的示例中,`步骤` `concreteStep1` 继承自 `parentStep`。它被实例化时使用了 `itemReader`、`itemProcessor`、`itemWriter`、`startLimit=5` 和 `allowStartIfComplete=true`。此外,`concreteStep1` `步骤` 覆盖了 `commitInterval`,使其为 `5`,如下例所示:

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

`id` 属性在 job 元素内的步骤上仍然是必需的。这有两个原因:

  • 在持久化 `StepExecution` 时,`id` 被用作步骤名称。如果在同一个 Job 中的多个步骤中引用了相同的独立步骤,则会发生错误。

  • 创建作业流时,如本章后面所述,`next` 属性应指向流程中的步骤,而不是独立的步骤。

抽象 `步骤`

有时,可能需要定义一个不是完整的 `步骤` 配置的父 `步骤`。例如,如果 `reader`、`writer` 和 `tasklet` 属性在 `步骤` 配置中被省略,则初始化将失败。如果必须定义一个不包含这些属性中一个或多个的父步骤,则应使用 `abstract` 属性。一个 `abstract` `步骤` 只能被继承,不能被实例化。

在下面的示例中,如果 `步骤` (abstractParentStep) 没有被声明为抽象的,它将不会被实例化。`步骤` (concreteStep2) 具有 itemReaderitemWritercommit-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>

合并列表

`步骤` 上的一些可配置元素是列表,例如 <listeners/> 元素。如果父 `步骤` 和子 `步骤` 都声明了 <listeners/> 元素,子列表会覆盖父列表。为了允许子步骤向父步骤定义的列表中添加额外的监听器,每个列表元素都有一个 merge 属性。如果元素指定了 merge="true",那么子列表将与父列表合并,而不是覆盖它。

在下面的示例中,`步骤` "concreteStep3" 创建时带有两个监听器: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>