JobStep 属性的后期绑定

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

  • Java

  • XML

以下示例展示了 Java 中的后期绑定

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

以下示例展示了 XML 中的后期绑定

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 中从属性读取文件名

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

以下示例展示了如何在 XML 中从属性读取文件名

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 允许对各种 JobStep 属性进行后期绑定。

  • Java

  • XML

以下示例展示了如何在 Java 中参数化文件名

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

以下示例展示了如何在 XML 中参数化文件名

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

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

  • Java

  • XML

以下示例展示了如何在 Java 中访问 ExecutionContext

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

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

XML 配置
<bean id="flatFileItemReader" scope="step"
      class="org.springframework.batch.infrastructure.item.file.FlatFileItemReader">
    <property name="resource" value="#{jobExecutionContext['input.file.name']}" />
</bean>
XML 配置
<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 中绑定到步骤作用域的示例

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

以下示例展示了在 XML 中绑定到步骤作用域的示例

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 中绑定到作业作用域的示例

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

以下示例展示了在 XML 中绑定到作业作用域的示例

XML 配置
<bean id="..." class="..." scope="job">
    <property name="name" value="#{jobParameters[input]}" />
</bean>
XML 配置
<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 正确创建实现此接口的代理,从而通过按预期调用 openupdateclose 方法来遵守其契约。

建议使此类 bean 的 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();
}
© . This site is unofficial and not affiliated with VMware.