我实际上正在使用Spring Batch,并且我一直在问自己一些有关泛型方法的问题。考虑以下代码:
public <I, O> SimpleStepBuilder<I, O> chunk(int chunkSize) {
return new SimpleStepBuilder<I, O>(this).chunk(chunkSize);
}
如果我们检查一下源代码,就会发现:
public SimpleStepBuilder<I, O> reader(ItemReader<? extends I> reader) {
this.reader = reader;
return this;
}
我不喜欢通过像这样链接电话:
@Bean
public Step step(final AccountReader accountReader, final AccountProcessor accountProcessor) {
return stepBuilderFactory.get("step")
.<COR_ACC_ACCOUNT, Account>chunk(10)
.reader(accountReader)
.processor(accountProcessor)
.writer(new JsonWriter<>())
.build();
}
reader()
方法将需要一个ItemProcessor<COR_ACC_ACCOUNT>
我发现这种凉爽可以保持类型安全。
现在是我的问题。给出以下代码:
@Component
public class ItemDictionary {
private final Map<Class, ItemReader> itemReaders;
@Autowired
public ItemDictionary(final List<ItemReader> readers) {
itemReaders = readers.stream().collect(Collectors.toMap(
ItemReader::getClass,
Function.identity()
));
public <I> ItemReader<I> getReader(final Class clazz) {
return itemReaders.get(clazz);
}
}
我想像这样定义上面定义的Step
:
@Bean
public Step step() {
return stepBuilderFactory.get("step")
.<COR_ACC_ACCOUNT, Account>chunk(10)
.reader(<COR_ACC_ACCOUNT>itemDictionary.getReader(AccountReader.class))
.processor(accountProcessor)
.writer(new JsonWriter<>())
.build();
}
itemDictionary
基本上是一个Map,其中包含我Spring上下文中存在的所有ItemReader
实现。
编译器拒绝此调用<COR_ACC_ACCOUNT>itemDictionary.getReader(AccountReader.class)
作为illegal start of expression
我想念什么吗?
是否仍然可以使用ItemDictionnary
保留类型安全检查?
答案 0 :(得分:1)
是的,在Java中该语法实际上是错误的。
您无法在此处保留类型安全性,因为在将实现存储到private final Map<Class, ItemReader> itemReaders
我建议最简单的解决方案是进行类型转换:
(ItemReader<COR_ACC_ACCOUNT>) itemDictionary.getReader(AccountReader.class)
或者,如果您要解释COR_ACC_ACCOUNT
是什么,我们可以做进一步的介绍。我感觉这是一个通用类型,对吗?
@Bean
public Step step() {
return stepBuilderFactory.get("step")
.<COR_ACC_ACCOUNT, Account>chunk(10)
.reader((ItemReader<COR_ACC_ACCOUNT>) itemDictionary.getReader(AccountReader.class))
.processor(accountProcessor)
.writer(new JsonWriter<>())
.build();
}
答案 1 :(得分:0)
根据.<COR_ACC_ACCOUNT, Account>chunk(10)
,要读取的项目类型为COR_ACC_ACCOUNT
,因此AccountReader
应该返回该类型的项目,在这种情况下,您无需在此处进行强制转换:< / p>
.reader(<COR_ACC_ACCOUNT>itemDictionary.getReader(AccountReader.class))
我尝试了您的示例,但没有编译错误:
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableBatchProcessing
public class MyJob {
@Autowired
private JobBuilderFactory jobs;
@Autowired
private StepBuilderFactory steps;
@Bean
public ItemDictionary itemDictionary() {
return new ItemDictionary(Arrays.asList(new FooReader()));
}
@Bean
public ItemWriter<Bar> itemWriter() {
return null;
}
@Bean
public Step step() {
return steps.get("step")
.<Foo, Bar>chunk(5)
.reader(itemDictionary().getReader(Foo.class))
.writer(itemWriter())
.build();
}
@Bean
public Job job() {
return jobs.get("job")
.start(step())
.build();
}
public class ItemDictionary {
private Map<Class, ItemReader> itemReaders;
public ItemDictionary(final List<ItemReader> readers) {
itemReaders = readers.stream().collect(Collectors.toMap(
ItemReader::getClass,
Function.identity()
));
}
public <I> ItemReader<I> getReader(final Class clazz) {
return itemReaders.get(clazz);
}
}
class Foo { }
class Bar { }
class FooReader implements ItemReader<Foo> {
@Override
public Foo read() {
return null;
}
}
}
希望这会有所帮助。