Job 和 Step 屬性的後期繫結
前面展示的 XML 和平面檔案示例都使用 Spring Resource 抽象來獲取檔案。這之所以有效,是因為 Resource 有一個 getFile 方法,它返回一個 java.io.File。您可以使用標準的 Spring 構造來配置 XML 和平面檔案資源
-
Java
-
XML
以下示例展示了 Java 中的後期繫結
@Bean
public FlatFileItemReader flatFileItemReader() {
FlatFileItemReader<Foo> reader = new FlatFileItemReaderBuilder<Foo>()
.name("flatFileItemReader")
.resource(new FileSystemResource("file://outputs/file.txt"))
...
}
以下示例展示了 XML 中的後期繫結
<bean id="flatFileItemReader"
class="org.springframework.batch.infrastructure.item.file.FlatFileItemReader">
<property name="resource"
value="file://outputs/file.txt" />
</bean>
上述 Resource 從指定的檔案系統位置載入檔案。請注意,絕對位置必須以雙斜槓(//)開頭。在大多數 Spring 應用程式中,此解決方案已足夠好,因為這些資源的名稱在編譯時是已知的。然而,在批處理場景中,檔名可能需要在執行時作為作業的引數來確定。這可以透過使用 -D 引數讀取系統屬性來解決。
-
Java
-
XML
以下展示瞭如何在 Java 中從屬性讀取檔名
@Bean
public FlatFileItemReader flatFileItemReader(@Value("${input.file.name}") String name) {
return new FlatFileItemReaderBuilder<Foo>()
.name("flatFileItemReader")
.resource(new FileSystemResource(name))
...
}
以下示例展示瞭如何在 XML 中從屬性讀取檔名
<bean id="flatFileItemReader"
class="org.springframework.batch.infrastructure.item.file.FlatFileItemReader">
<property name="resource" value="${input.file.name}" />
</bean>
此解決方案要起作用,只需要一個系統引數(例如 -Dinput.file.name="file://outputs/file.txt")。
儘管您可以在此處使用 PropertyPlaceholderConfigurer,但如果系統屬性始終設定,則沒有必要,因為 Spring 中的 ResourceEditor 已經過濾並對系統屬性進行佔位符替換。 |
通常,在批處理設定中,最好在作業的 JobParameters 中引數化檔名(而不是透過系統屬性)並以這種方式訪問它們。為了實現這一點,Spring Batch 允許對各種 Job 和 Step 屬性進行後期繫結。
-
Java
-
XML
以下示例展示瞭如何在 Java 中引數化檔名
@StepScope
@Bean
public FlatFileItemReader flatFileItemReader(@Value("#{jobParameters['input.file.name']}") String name) {
return new FlatFileItemReaderBuilder<Foo>()
.name("flatFileItemReader")
.resource(new FileSystemResource(name))
...
}
以下示例展示瞭如何在 XML 中引數化檔名
<bean id="flatFileItemReader" scope="step"
class="org.springframework.batch.infrastructure.item.file.FlatFileItemReader">
<property name="resource" value="#{jobParameters['input.file.name']}" />
</bean>
您可以以相同的方式訪問 JobExecution 和 StepExecution 級別的 ExecutionContext。
-
Java
-
XML
以下示例展示瞭如何在 Java 中訪問 ExecutionContext
@StepScope
@Bean
public FlatFileItemReader flatFileItemReader(@Value("#{jobExecutionContext['input.file.name']}") String name) {
return new FlatFileItemReaderBuilder<Foo>()
.name("flatFileItemReader")
.resource(new FileSystemResource(name))
...
}
@StepScope
@Bean
public FlatFileItemReader flatFileItemReader(@Value("#{stepExecutionContext['input.file.name']}") String name) {
return new FlatFileItemReaderBuilder<Foo>()
.name("flatFileItemReader")
.resource(new FileSystemResource(name))
...
}
以下示例展示瞭如何在 XML 中訪問 ExecutionContext
<bean id="flatFileItemReader" scope="step"
class="org.springframework.batch.infrastructure.item.file.FlatFileItemReader">
<property name="resource" value="#{jobExecutionContext['input.file.name']}" />
</bean>
<bean id="flatFileItemReader" scope="step"
class="org.springframework.batch.infrastructure.item.file.FlatFileItemReader">
<property name="resource" value="#{stepExecutionContext['input.file.name']}" />
</bean>
任何使用後期繫結的 bean 都必須宣告 scope="step"。有關更多資訊,請參閱步驟作用域。Step bean 不應是步驟作用域或作業作用域的。如果步驟定義中需要後期繫結,則應將該步驟的元件(任務、項讀取器/寫入器、完成策略等)進行作用域化。 |
| 如果您使用 Spring 3.0(或更高版本),步驟作用域 bean 中的表示式是 Spring 表示式語言,這是一種功能強大的通用語言,具有許多有趣的特性。為了提供向後相容性,如果 Spring Batch 檢測到存在較舊版本的 Spring,它會使用一種功能較弱且解析規則略有不同的原生表示式語言。主要區別在於,在 Spring 2.5 中,上述示例中的對映鍵不需要加引號,但在 Spring 3.0 中,引號是強制性的。 |
步驟作用域
前面展示的所有後期繫結示例都在 bean 定義上聲明瞭 step 作用域。
-
Java
-
XML
以下示例展示了在 Java 中繫結到步驟作用域的示例
@StepScope
@Bean
public FlatFileItemReader flatFileItemReader(@Value("#{jobParameters[input.file.name]}") String name) {
return new FlatFileItemReaderBuilder<Foo>()
.name("flatFileItemReader")
.resource(new FileSystemResource(name))
...
}
以下示例展示了在 XML 中繫結到步驟作用域的示例
<bean id="flatFileItemReader" scope="step"
class="org.springframework.batch.infrastructure.item.file.FlatFileItemReader">
<property name="resource" value="#{jobParameters[input.file.name]}" />
</bean>
使用 Step 作用域是使用後期繫結所必需的,因為只有當 Step 開始時,bean 才能真正例項化,以便找到屬性。由於它預設不是 Spring 容器的一部分,因此必須透過使用 batch 名稱空間、透過顯式包含 StepScope 的 bean 定義或透過使用 @EnableBatchProcessing 註解來顯式新增作用域。只使用其中一種方法。以下示例使用 batch 名稱空間
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="...">
<batch:job .../>
...
</beans>
以下示例顯式包含 bean 定義
<bean class="org.springframework.batch.core.scope.StepScope" />
作業作用域
Job 作用域,在 Spring Batch 3.0 中引入,在配置上與 Step 作用域相似,但它是 Job 上下文的作用域,因此每個正在執行的作業只有一個這樣的 bean 例項。此外,透過使用 #{..} 佔位符,提供了對從 JobContext 可訪問的引用進行後期繫結的支援。使用此功能,您可以從作業或作業執行上下文以及作業引數中提取 bean 屬性。
-
Java
-
XML
以下示例展示了在 Java 中繫結到作業作用域的示例
@JobScope
@Bean
public FlatFileItemReader flatFileItemReader(@Value("#{jobParameters[input]}") String name) {
return new FlatFileItemReaderBuilder<Foo>()
.name("flatFileItemReader")
.resource(new FileSystemResource(name))
...
}
@JobScope
@Bean
public FlatFileItemReader flatFileItemReader(@Value("#{jobExecutionContext['input.name']}") String name) {
return new FlatFileItemReaderBuilder<Foo>()
.name("flatFileItemReader")
.resource(new FileSystemResource(name))
...
}
以下示例展示了在 XML 中繫結到作業作用域的示例
<bean id="..." class="..." scope="job">
<property name="name" value="#{jobParameters[input]}" />
</bean>
<bean id="..." class="..." scope="job">
<property name="name" value="#{jobExecutionContext['input.name']}.txt" />
</bean>
由於它預設不是 Spring 容器的一部分,因此必須透過使用 batch 名稱空間、透過顯式包含 JobScope 的 bean 定義或透過使用 @EnableBatchProcessing 註解來顯式新增作用域(只選擇一種方法)。以下示例使用 batch 名稱空間
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="...">
<batch:job .../>
...
</beans>
以下示例包含一個顯式定義 JobScope 的 bean
<bean class="org.springframework.batch.core.scope.JobScope" />
| 在多執行緒或分割槽步驟中使用作業作用域 bean 存在一些實際限制。Spring Batch 不控制在這些用例中生成的執行緒,因此無法正確設定它們以使用此類 bean。因此,我們不建議在多執行緒或分割槽步驟中使用作業作用域 bean。 |
作用域 ItemStream 元件
當使用 Java 配置風格定義作業或步驟作用域的 ItemStream bean 時,bean 定義方法的返回型別應至少為 ItemStream。這是必需的,以便 Spring Batch 正確建立實現此介面的代理,從而透過按預期呼叫 open、update 和 close 方法來遵守其契約。
建議使此類 bean 的 bean 定義方法返回最具體的已知實現,如下例所示
@Bean
@StepScope
public FlatFileItemReader flatFileItemReader(@Value("#{jobParameters['input.file.name']}") String name) {
return new FlatFileItemReaderBuilder<Foo>()
.resource(new FileSystemResource(name))
// set other properties of the item reader
.build();
}