Java Spring-batch @BeforeStep 不适用于 @StepScope
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21241683/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring-batch @BeforeStep does not work with @StepScope
提问by Géraud
I'm using Spring Batch version 2.2.4.RELEASE I tried to write a simple example with stateful ItemReader, ItemProcessor and ItemWriter beans.
我正在使用 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;
}
}
In my integration test, I'm declaring my beans in an inner static java config class like the one below:
在我的集成测试中,我在内部静态 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());
}
}
This test passes.
此测试通过。
But as soon as I define my StatefulItemReaderas a step scoped bean (which is better for a stateful reader), the "before step" code is no longer executed.
但是一旦我将StatefulItemReader定义为 step 范围的 bean(这对有状态的读者来说更好),“before step”代码就不再执行。
...
@Bean
@StepScope
public ItemReader<String> reader() {
return new StatefulItemReader();
}
...
And I notice the same issue with processor and my writer beans.
我注意到处理器和我的编写器 bean 也存在同样的问题。
What's wrong with my code? Is it related to this resolved issue: https://jira.springsource.org/browse/BATCH-1230
我的代码有什么问题?是否与这个已解决的问题有关:https: //jira.springsource.org/browse/BATCH-1230
My whole Maven project with several JUnit tests can be found on GitHub: https://github.com/galak75/spring-batch-step-scope
我的整个 Maven 项目和几个 JUnit 测试可以在 GitHub 上找到:https: //github.com/galak75/spring-batch-step-scope
Thank you in advance for your answers.
预先感谢您的回答。
采纳答案by Michael Minella
When you configure a bean as follows:
当您按如下方式配置 bean 时:
@Bean
@StepScope
public MyInterface myBean() {
return new MyInterfaceImpl();
}
You are telling Spring to use the proxy mode ScopedProxyMode.TARGET_CLASS
. However, by returning the MyInterface
, instead of the MyInterfaceImpl
, the proxy only has visibility into the methods on the MyInterface
. This prevents Spring Batch from being able to find the methods on MyInterfaceImpl
that have been annotated with the listener annotations like @BeforeStep
. The correct way to configure this is to return MyInterfaceImpl
on your configuration method like below:
您是在告诉 Spring 使用代理模式ScopedProxyMode.TARGET_CLASS
。但是,通过返回MyInterface
,而不是MyInterfaceImpl
,代理只能查看 上的方法MyInterface
。这可以防止 Spring Batch 找到MyInterfaceImpl
已使用侦听器注释(如@BeforeStep
. 配置它的正确方法是返回MyInterfaceImpl
您的配置方法,如下所示:
@Bean
@StepScope
public MyInterfaceImpl myBean() {
return new MyInterfaceImpl();
}
We have added a warning log message on startup that points out, as we look for the annotated listener methods, if the object is proxied and the target is an interface, we won't be able to find methods on the implementing class with annotations on them.
我们在启动时添加了一条警告日志消息,指出当我们寻找带注释的侦听器方法时,如果对象是代理的并且目标是接口,我们将无法在带有注释的实现类上找到方法他们。