重用现有服务

批处理系统通常与其他应用程序风格结合使用。最常见的是在线系统,但它也可以通过移动每种应用程序风格所需的大量数据来支持集成甚至胖客户端应用程序。因此,许多用户希望在其批处理 Job 中重用现有的 DAO 或其他服务是很常见的。Spring 容器本身通过允许注入任何必要的类来使这变得相当容易。但是,在某些情况下,现有服务需要充当 `ItemReader` 或 `ItemWriter`,这可能是为了满足另一个 Spring Batch 类的依赖关系,或者因为它确实是某个 Step 的主要 `ItemReader`。为每个需要包装的服务编写一个适配器类是相当简单的,但由于这是一个非常常见的问题,Spring Batch 提供了实现:`ItemReaderAdapter` 和 `ItemWriterAdapter`。这两个类都通过调用委派模式(delegate pattern)实现了标准的 Spring 方法,并且设置起来非常简单。

  • Java

  • XML

以下 Java 示例使用了 `ItemReaderAdapter`

Java 配置
@Bean
public ItemReaderAdapter itemReader() {
	ItemReaderAdapter reader = new ItemReaderAdapter();

	reader.setTargetObject(fooService());
	reader.setTargetMethod("generateFoo");

	return reader;
}

@Bean
public FooService fooService() {
	return new FooService();
}

以下 XML 示例使用了 `ItemReaderAdapter`

XML 配置
<bean id="itemReader" class="org.springframework.batch.item.adapter.ItemReaderAdapter">
    <property name="targetObject" ref="fooService" />
    <property name="targetMethod" value="generateFoo" />
</bean>

<bean id="fooService" class="org.springframework.batch.item.sample.FooService" />

需要注意的一个重点是,`targetMethod` 的契约必须与 `read` 的契约相同:当耗尽时,它返回 `null`。否则,它返回一个 `Object`。任何其他返回值都会阻止框架知道何时应该结束处理,这可能导致无限循环或不正确的失败,具体取决于 `ItemWriter` 的实现。

  • Java

  • XML

以下 Java 示例使用了 `ItemWriterAdapter`

Java 配置
@Bean
public ItemWriterAdapter itemWriter() {
	ItemWriterAdapter writer = new ItemWriterAdapter();

	writer.setTargetObject(fooService());
	writer.setTargetMethod("processFoo");

	return writer;
}

@Bean
public FooService fooService() {
	return new FooService();
}

以下 XML 示例使用了 `ItemWriterAdapter`

XML 配置
<bean id="itemWriter" class="org.springframework.batch.item.adapter.ItemWriterAdapter">
    <property name="targetObject" ref="fooService" />
    <property name="targetMethod" value="processFoo" />
</bean>

<bean id="fooService" class="org.springframework.batch.item.sample.FooService" />