Универсальные методы в шаге SpringBatch - PullRequest
0 голосов
/ 17 октября 2018

Я на самом деле использую 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 - это, в основном, Карта, содержащая все ItemReaderреализации, присутствующие в моем контексте Spring.

Этот вызов <COR_ACC_ACCOUNT>itemDictionary.getReader(AccountReader.class) отклонен компилятором как illegal start of expression

Я что-то упустил?

Возможно ли ещесохранить тип безопасной проверки с помощью ItemDictionnary?

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Согласно .<COR_ACC_ACCOUNT, Account>chunk(10), тип предметов для чтения равен COR_ACC_ACCOUNT, поэтому AccountReader должен возвращать предметы этого типа, в этом случае вам здесь не нужен приведение:

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

}

Надеюсь, это поможет.

0 голосов
/ 17 октября 2018

Да, этот синтаксис на самом деле неверен в 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();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...