Java SpringBatch的Step块中的泛型方法

Java SpringBatch的Step块中的泛型方法,java,generics,syntax,spring-batch,Java,Generics,Syntax,Spring Batch,我实际上在使用SpringBatch,我一直在问自己一些关于泛型方法的问题。考虑到以下代码: public <I, O> SimpleStepBuilder<I, O> chunk(int chunkSize) { return new SimpleStepBuilder<I, O>(this).chunk(chunkSize); } 我想这样定义上面定义的步骤: @Bean public Step step(final AccountReader

我实际上在使用SpringBatch,我一直在问自己一些关于泛型方法的问题。考虑到以下代码:

public <I, O> SimpleStepBuilder<I, O> chunk(int chunkSize) {
    return new SimpleStepBuilder<I, O>(this).chunk(chunkSize);
}
我想这样定义上面定义的步骤:

@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();
}
@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基本上是一个包含Spring上下文中所有ItemReader实现的映射

此调用itemDictionary.getReaderAccountReader.class被编译器拒绝,因为它是表达式的非法开始

我错过什么了吗


仍然可以使用ItemDictionnary保留类型安全检查吗?

是的,这种语法在java中实际上是错误的

您不能在这里保留类型安全性,因为当您将实现存储到私有最终映射项阅读器时,已经失去了类型安全性

我建议最简单的解决方案是进行类型转换:

(ItemReader<COR_ACC_ACCOUNT>) itemDictionary.getReader(AccountReader.class)
根据.chunk10,要读取的项目类型是COR_ACC_ACCOUNT,因此AccountReader应该返回这种类型的项目,在这种情况下,您不需要在此处进行转换:

.readeritemDictionary.getReaderAccountReader.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;
        }
    }

}

希望这能有所帮助。

我承认,这个COR_ACC_账户只是一个名字古怪的POJO。它保存来自数据库的数据,仅此而已。没有涉及泛型类型。我检查了您的示例,实际上在删除它之后,它运行良好,没有任何编译错误或警告。事实上,这是正确的解决方案。请你更新你的答案,以便我能验证它?
(ItemReader<COR_ACC_ACCOUNT>) itemDictionary.getReader(AccountReader.class)
    @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();
    }
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;
        }
    }

}