繼承自父 `步驟`

如果一組 `步驟` 共享相似的配置,那麼定義一個“父” `步驟`,具體的 `步驟` 可以從其繼承屬性,可能會有所幫助。類似於 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>