Spring 批处理 - 在具有 reader 和编写器的步骤中配置 Tasklet?

Spring Batch - Configure Tasklet in Step having reader and writer?

我正在使用 Spring 批量启动示例。在此示例中,我希望将基于 XML 的应用程序转换为基于注释的应用程序。但是,我正在努力在步骤中使用@Bean 进行配置以创建准确的配置。

    <batch:step id="step1">
        <batch:tasklet>
            <batch:chunk reader="paymentDataReader" writer="paymentDataWriter" commit-interval="100000">
                <batch:listeners>
                    <batch:listener ref="paymentingStepExecutionListener" />
                </batch:listeners>
            </batch:chunk>
        </batch:tasklet>
        <batch:next on="COMPLETED" to="sendpaymentingBatchFiles" />
    </batch:step>

JobConfiguration.java

    @Configuration
    public class JobConfiguration {
        @Autowired
        private JobBuilderFactory jobBuilderFactory;

        @Autowired
        private StepBuilderFactory stepBuilderFactory;

        @Autowired
        private DataSource dataSource;

        @Bean
        @StepScope
        public PaymentContextTasklet paymentContextTasklet() {
            return new PaymentContextTasklet();
        }

        // Either execute for "Payment" or "Order"
        @Bean
        public ContextDecider contextDecider() {
            return new ContextDecider();
        }

        @Bean
        public JdbcPagingItemReader<Payment> pagingItemReader(){
            JdbcPagingItemReader<Payment> reader = new JdbcPagingItemReader<>();
            reader.setDataSource(this.dataSource);
            reader.setFetchSize(10);
            reader.setRowMapper(new PaymentRowMapper());

            MySqlPagingQueryProvider queryProvider = new MySqlPagingQueryProvider();
            queryProvider.setSelectClause("select paymentId, amount, customerId, paymentDate");
            queryProvider.setFromClause("from payment");

            reader.setQueryProvider(queryProvider);
            return reader;
        }

        @Bean
        public ItemWriter<Payment> paymentItemWriter(){
            return items -> {
                for(Payment c : items) {
                    System.out.println(c.toString());
                }
            };
        }

        @Bean
        public PaymentStepExecutionListener paymentStepExecutionListener() {
            return new PaymentStepExecutionListener();
        }

        @Bean
        public Step step1() {
            return stepBuilderFactory.get("step1")
                    .<Payment, Payment>chunk(10)
                    .reader(pagingItemReader())
                    .writer(paymentItemWriter())
                    .tasklet(paymentStepExecutionListener())
                    .rea
                    .build();
        }

        @Bean
        @StepScope
        public PaymentDataTasklet paymentDataTasklet() {
            return new PaymentDataTasklet();
        }

        @Bean
        public Step paymentContextStep() {
            return stepBuilderFactory.get("paymentContextStep")
                    .tasklet(paymentContextTasklet())
                    .build();
        }

        @Bean
        public Step paymentDataStep() {
            return stepBuilderFactory.get("paymentDataStep")
                    .tasklet(paymentDataTasklet())
                    .build();
        }

        @Bean
        public Step endStep() {
            return stepBuilderFactory.get("endStep")
                    .tasklet(null)
                    .build();
        }

        @Bean
        public Job paymentDataBatchJob() {
            return jobBuilderFactory.get("paymentDataBatchJob")
                    .start(paymentContextStep())
                    .next(contextDecider())
                        .on("Payment").to(paymentDataStep()).on("COMPLETED").to(endStep)
                    .from(contextDecider())
                        .on("Order").to(endStep()).end()
                    .build();
        }
    }

However I am struggling to configure using @Bean in Step to create exact configuration.

Java 配置中的 XML 片段相当于:

   @Bean
    public Step step1() {
        return stepBuilderFactory.get("step1")
                .<Payment, Payment>chunk(100000)
                .reader(paymentDataReader())
                .writer(paymentDataWriter())
                .listener(paymentingStepExecutionListener())
                .build();
    }

    @Bean
    public Job paymentDataBatchJob() {
        return jobBuilderFactory.get("paymentDataBatchJob")
                .start(step1())
                .next(sendpaymentingBatchFiles())
                .build();
    }

感谢@Mahmoud Ben Hassine。我意识到我应该在 listener 中使用 paymentStepExecutionListener 而不是在 Tasklet.

还有一件事是 StepExecutionListener 只能在 scope="step". 中定义的 bean 中工作,所以我应该使用

// 您只能在 //scope="step".

中定义的 bean 中访问 stepExecutionContext
@Bean
@StepScope
public PaymentStepExecutionListener paymentStepExecutionListener() {
    return new PaymentStepExecutionListener();
}

现在一切正常。