Spring-batch @BeforeStep不适用于@StepScope
我正在使用Spring Batch版本2.2.4.RELEASE我试着用有状态的ItemReader,ItemProcessor和ItemWriter bean编写一个简单的例子。
public class StatefulItemReader implements ItemReader { private List 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") .chunk(1) .reader(reader()) .processor(processor()) .writer(writer()) .build(); } @Bean public ItemReader reader() { return new StatefulItemReader(); } @Bean public ItemProcessor processor() { return new StatefulItemProcessor(); } @Bean public ItemWriter writer() { return new StatefulItemWriter(); } } @Autowired JobLauncherTestUtils jobLauncherTestUtils; @Test public void testStepExecution() { JobExecution jobExecution = jobLauncherTestUtils.launchStep("step-under-test"); assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); } }
这个测试通过。
但是一旦我将StatefulItemReader定义为步骤范围的bean(对于有状态的读者来说更好),就不再执行“before step”代码了。
... @Bean @StepScope public ItemReader reader() { return new StatefulItemReader(); } ...
我注意到处理器和我的编写器bean的相同问题。
我的代码出了什么问题? 是否与此已解决的问题有关: https : //jira.springsource.org/browse/BATCH-1230
我可以在GitHub上找到我的几个JUnit测试的整个Maven项目: 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(); }
我们在启动时添加了一条警告日志消息,指出当我们查找带注释的侦听器方法时,如果对象被代理并且目标是接口,我们将无法在带有注释的实现类上找到方法他们。