Late Binding of Job and Step Attributes

前面显示的 XML 和平面文件示例都使用 Spring Resource 抽象来获取文件。这有效,因为 Resource 有一个 getFile 方法,它返回一个 java.io.File。您可以使用标准 Spring 结构配置 XML 和平面文件资源:

Java

以下示例显示了 Java 中的延迟绑定:

Java Configuration
@Bean
public FlatFileItemReader flatFileItemReader() {
	FlatFileItemReader<Foo> reader = new FlatFileItemReaderBuilder<Foo>()
			.name("flatFileItemReader")
			.resource(new FileSystemResource("file://outputs/file.txt"))
			...
}
XML

以下示例显示 XML 中的延迟绑定:

XML Configuration
<bean id="flatFileItemReader"
      class="org.springframework.batch.item.file.FlatFileItemReader">
    <property name="resource"
              value="file://outputs/file.txt" />
</bean>

前一个 Resource 从指定的 file 系统位置装入文件。注意绝对路径必须以双斜杠 (//) 开头。在大多数 Spring 应用程序中,该解决方案足够好,因为这些资源的名称在编译时已知。然而,在批处理 scenario 中,可能需要在运行时将文件名称视作作业参数来确定。这可以通过 -D 参数来读取系统属性来解决。

Java

以下是显示如何从 Java 中的属性读取文件的示例:

Java Configuration
@Bean
public FlatFileItemReader flatFileItemReader(@Value("${input.file.name}") String name) {
	return new FlatFileItemReaderBuilder<Foo>()
			.name("flatFileItemReader")
			.resource(new FileSystemResource(name))
			...
}
XML

以下示例显示如何从 XML 中的属性读取文件名称:

XML Configuration
<bean id="flatFileItemReader"
      class="org.springframework.batch.item.file.FlatFileItemReader">
    <property name="resource" value="${input.file.name}" />
</bean>

要使该解决方案发挥作用,需要一个系统参数(如 -Dinput.file.name="file://outputs/file.txt")。

虽然您可以使用 PropertyPlaceholderConfigurer,但如果系统属性始终设置,则此属性并非必需,因为 Spring 中的 ResourceEditor 已对系统属性进行过滤和占位符替换。

通常,在批量设置中,最好在作业的 JobParameters 中参数化文件名(而不是通过系统属性),然后再访问这些参数。为了完成此操作,Spring Batch 允许延迟绑定各种 JobStep 属性。

Java

以下示例显示如何用 Java 参数化文件名:

Java Configuration
@StepScope
@Bean
public FlatFileItemReader flatFileItemReader(@Value("#{jobParameters['input.file.name']}") String name) {
	return new FlatFileItemReaderBuilder<Foo>()
			.name("flatFileItemReader")
			.resource(new FileSystemResource(name))
			...
}
XML

以下示例显示如何在 XML 中参数化文件名:

XML Configuration
<bean id="flatFileItemReader" scope="step"
      class="org.springframework.batch.item.file.FlatFileItemReader">
    <property name="resource" value="#{jobParameters['input.file.name']}" />
</bean>

你可以以相同的方式访问 JobExecutionStepExecution 级别的 ExecutionContext

Java

以下示例显示如何用 Java 访问 ExecutionContext

Java Configuration
@StepScope
@Bean
public FlatFileItemReader flatFileItemReader(@Value("#{jobExecutionContext['input.file.name']}") String name) {
	return new FlatFileItemReaderBuilder<Foo>()
			.name("flatFileItemReader")
			.resource(new FileSystemResource(name))
			...
}
Java Configuration
@StepScope
@Bean
public FlatFileItemReader flatFileItemReader(@Value("#{stepExecutionContext['input.file.name']}") String name) {
	return new FlatFileItemReaderBuilder<Foo>()
			.name("flatFileItemReader")
			.resource(new FileSystemResource(name))
			...
}
XML

以下示例显示如何在 XML 中访问 ExecutionContext

XML Configuration
<bean id="flatFileItemReader" scope="step"
      class="org.springframework.batch.item.file.FlatFileItemReader">
    <property name="resource" value="#{jobExecutionContext['input.file.name']}" />
</bean>
XML Configuration
<bean id="flatFileItemReader" scope="step"
      class="org.springframework.batch.item.file.FlatFileItemReader">
    <property name="resource" value="#{stepExecutionContext['input.file.name']}" />
</bean>

任何使用后期绑定的 Bean 都必须声明为`scope="step"`。有关更多信息,请参阅Step Scope。 `Step`Bean 不应为 step 范围。如果 step 定义中需要后期绑定,则该 step 的组件(任务项、项读取器或写入器等)应改为范围约束。

如果您使用 Spring 3.0(或更高版本),则步骤作用域 Bean 中的表达式将采用 Spring 表达式语言,这是一种功能强大的通用语言,具有许多有趣的功能。为了提供向后兼容性,如果 Spring Batch 检测到更低版本的 Spring,它将使用功能较弱、解析规则略有不同的本机表达式语言。主要区别在于,上面示例中的 map 键无需在 Spring 2.5 中使用引号,但在 Spring 3.0 中,引号是必需的。

Step Scope

所有前面展示的延迟绑定示例都在 bean 的定义中声明了 step 作用域。

Java

以下示例展示了 Java 中绑定到 step 作用域的示例:

Java Configuration
@StepScope
@Bean
public FlatFileItemReader flatFileItemReader(@Value("#{jobParameters[input.file.name]}") String name) {
	return new FlatFileItemReaderBuilder<Foo>()
			.name("flatFileItemReader")
			.resource(new FileSystemResource(name))
			...
}
XML

以下示例显示了 XML 中绑定到 step 作用域的示例:

XML Configuration
<bean id="flatFileItemReader" scope="step"
      class="org.springframework.batch.item.file.FlatFileItemReader">
    <property name="resource" value="#{jobParameters[input.file.name]}" />
</bean>

使用 Step 作用域需要使用延迟绑定,因为在此 bean 可以实际实例化之前,Step 不能启动,以便查找属性。由于缺省情况下它不是 Spring 容器的一部分,因此必须采用以下方式显式添加这个 scope:使用 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 Scope

自 Spring Batch 3.0 引入以来,Job scope 配置与 Step scope 类似,但它是 Job context 的一个 scope,因此每运行一个作业,此类 bean 只有一个实例。此外,还支持通过 #{..} 占位符延迟绑定可以从 JobContext 访问的引用。通过该特性,你可以从 Job 或 Job 执行 context 以及 Job 参数中提取 bean 属性。

Java

以下示例展示在 Java 中绑定到 Job scope 的示例:

Java Configuration
@JobScope
@Bean
public FlatFileItemReader flatFileItemReader(@Value("#{jobParameters[input]}") String name) {
	return new FlatFileItemReaderBuilder<Foo>()
			.name("flatFileItemReader")
			.resource(new FileSystemResource(name))
			...
}
Java Configuration
@JobScope
@Bean
public FlatFileItemReader flatFileItemReader(@Value("#{jobExecutionContext['input.name']}") String name) {
	return new FlatFileItemReaderBuilder<Foo>()
			.name("flatFileItemReader")
			.resource(new FileSystemResource(name))
			...
}
XML

以下示例展示在 XML 中绑定到 Job scope 的示例:

XML Configuration
<bean id="..." class="..." scope="job">
    <property name="name" value="#{jobParameters[input]}" />
</bean>
XML Configuration
<bean id="..." class="..." scope="job">
    <property name="name" value="#{jobExecutionContext['input.name']}.txt" />
</bean>

由于缺省情况下它不是 Spring 容器的一部分,因此必须通过以下方式显式添加该 scope:使用 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。

Scoping ItemStream components

使用 Java 配置方式来定义作业或步骤作用域的 ItemStream Bean 时,Bean 定义方法的返回类型至少应该是 ItemStream。这是必需的,以便 Spring Batch 正确创建实现此接口的代理,并因此通过按预期调用 openupdateclose 方法来履行其契约。

建议让此类 Bean 的 Bean 定义方法返回最明确已知实现,如下例所示:

Define a step-scoped bean with the most specific return type
@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();
}