Late Binding of Job
and Step
Attributes
前面显示的 XML 和平面文件示例都使用 Spring Resource
抽象来获取文件。这有效,因为 Resource
有一个 getFile
方法,它返回一个 java.io.File
。您可以使用标准 Spring 结构配置 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.item.file.FlatFileItemReader">
<property name="resource"
value="file://outputs/file.txt" />
</bean>
前一个 Resource
从指定的 file 系统位置装入文件。注意绝对路径必须以双斜杠 (//
) 开头。在大多数 Spring 应用程序中,该解决方案足够好,因为这些资源的名称在编译时已知。然而,在批处理 scenario 中,可能需要在运行时将文件名称视作作业参数来确定。这可以通过 -D
参数来读取系统属性来解决。
- 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.item.file.FlatFileItemReader">
<property name="resource" value="${input.file.name}" />
</bean>
要使该解决方案发挥作用,需要一个系统参数(如 -Dinput.file.name="file://outputs/file.txt"
)。
虽然您可以使用 |
通常,在批量设置中,最好在作业的 JobParameters
中参数化文件名(而不是通过系统属性),然后再访问这些参数。为了完成此操作,Spring Batch 允许延迟绑定各种 Job
和 Step
属性。
- 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.item.file.FlatFileItemReader">
<property name="resource" value="#{jobParameters['input.file.name']}" />
</bean>
你可以以相同的方式访问 JobExecution
和 StepExecution
级别的 ExecutionContext
。
- Java
-
以下示例显示如何用 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
-
以下示例显示如何在 XML 中访问
ExecutionContext
:
<bean id="flatFileItemReader" scope="step"
class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="#{jobExecutionContext['input.file.name']}" />
</bean>
<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 作用域的示例:
@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 作用域的示例:
<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 的示例:
@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
-
以下示例展示在 XML 中绑定到 Job scope 的示例:
<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 容器的一部分,因此必须通过以下方式显式添加该 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 正确创建实现此接口的代理,并因此通过按预期调用 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();
}