[英]Spring-batch @BeforeStep does not work with @StepScope
我正在使用 Spring Batch 版本 2.2.4.RELEASE 我试图用有状态的 ItemReader、ItemProcessor 和 ItemWriter bean 编写一个简单的例子。
public class StatefulItemReader implements ItemReader<String> {
private List<String> list;
@BeforeStep
public void initializeState(StepExecution stepExecution) {
this.list = new ArrayList<>();
}
@AfterStep
public ExitStatus exploitState(StepExecution stepExecution) {
System.out.println("******************************");
System.out.println(" READING RESULTS : " + list.size());
return stepExecution.getExitStatus();
}
@Override
public String read() throws Exception {
this.list.add("some stateful reading information");
if (list.size() < 10) {
return "value " + list.size();
}
return null;
}
}
在我的集成测试中,我在内部静态 java 配置类中声明了我的 bean,如下所示:
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class SingletonScopedTest {
@Configuration
@EnableBatchProcessing
static class TestConfig {
@Autowired
private JobBuilderFactory jobBuilder;
@Autowired
private StepBuilderFactory stepBuilder;
@Bean
JobLauncherTestUtils jobLauncherTestUtils() {
return new JobLauncherTestUtils();
}
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder embeddedDatabaseBuilder = new EmbeddedDatabaseBuilder();
return embeddedDatabaseBuilder.addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql")
.addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql")
.setType(EmbeddedDatabaseType.HSQL)
.build();
}
@Bean
public Job jobUnderTest() {
return jobBuilder.get("job-under-test")
.start(stepUnderTest())
.build();
}
@Bean
public Step stepUnderTest() {
return stepBuilder.get("step-under-test")
.<String, String>chunk(1)
.reader(reader())
.processor(processor())
.writer(writer())
.build();
}
@Bean
public ItemReader<String> reader() {
return new StatefulItemReader();
}
@Bean
public ItemProcessor<String, String> processor() {
return new StatefulItemProcessor();
}
@Bean
public ItemWriter<String> writer() {
return new StatefulItemWriter();
}
}
@Autowired
JobLauncherTestUtils jobLauncherTestUtils;
@Test
public void testStepExecution() {
JobExecution jobExecution = jobLauncherTestUtils.launchStep("step-under-test");
assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
}
}
此测试通过。
但是一旦我将StatefulItemReader定义为 step 范围的 bean(这对有状态的读者来说更好),“before step”代码就不再执行。
...
@Bean
@StepScope
public ItemReader<String> reader() {
return new StatefulItemReader();
}
...
我注意到处理器和我的编写器 bean 也存在同样的问题。
我的代码有什么问题? 是否与这个已解决的问题有关: https : //jira.springsource.org/browse/BATCH-1230
我的整个 Maven 项目和几个 JUnit 测试可以在 GitHub 上找到: https : //github.com/galak75/spring-batch-step-scope
预先感谢您的回答。
当您按如下方式配置 bean 时:
@Bean
@StepScope
public MyInterface myBean() {
return new MyInterfaceImpl();
}
您告诉 Spring 使用代理模式ScopedProxyMode.TARGET_CLASS
。 但是,通过返回MyInterface
而不是MyInterfaceImpl
,代理只能看到MyInterface
上的方法。 这可以防止 Spring Batch 能够在MyInterfaceImpl
上找到已使用诸如@BeforeStep
类的侦听器注释进行注释的@BeforeStep
。 正确的配置方法是在你的配置方法中返回MyInterfaceImpl
,如下所示:
@Bean
@StepScope
public MyInterfaceImpl myBean() {
return new MyInterfaceImpl();
}
我们在启动时添加了一条警告日志消息,指出当我们寻找带注释的侦听器方法时,如果对象是代理的并且目标是接口,我们将无法在带有注释的实现类上找到方法他们。
正如pojo-guy所建议的,解决方案是实现 StepExecutionListener 和 Override beforeStep 方法来设置 stepExecution
@Override
public void beforeStep(StepExecution stepExecution) {
this.stepExecution = stepExecution;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.