如何通过@Value获取JobExecutionContext后向其写入上下文数据?
Spring Batch 作业执行上下文写入与作用域依赖问题解答
一、如何向JobExecutionContext写入数据
通过@Value("#{jobExecutionContext}")注入的是不可修改的Map包装器,这是Spring Batch为避免直接修改上下文引发并发问题做的限制。要写入数据到JobExecutionContext,需通过JobExecution对象操作:
1. 在Step组件中获取可修改的上下文
- ItemProcessor/ItemWriter场景:实现
StepExecutionListener接口,从StepExecution中拿到JobExecution,进而操作可修改的上下文:
public class CustomItemProcessor implements ItemProcessor<Foo, Bar>, StepExecutionListener { private StepExecution stepExecution; @Override public void beforeStep(StepExecution stepExecution) { this.stepExecution = stepExecution; } @Override public Bar process(Foo item) throws Exception { // 写入数据到JobExecutionContext stepExecution.getJobExecution().getExecutionContext().put("aa", "bb"); // 业务处理逻辑 return new Bar(item); } @Override public ExitStatus afterStep(StepExecution stepExecution) { return null; } }
- @JobScope/@StepScope Bean场景:直接注入
JobExecution或StepExecution对象,操作上下文:
@JobScope @Bean public FlatFileItemReader flatFileItemReader(JobExecution jobExecution) { // 写入数据 jobExecution.getExecutionContext().put("aa", "bb"); return new FlatFileItemReaderBuilder<Foo>() .name("flatFileItemReader") .resource(new FileSystemResource(jobExecution.getExecutionContext().getString("input.name"))) // 其他配置 .build(); }
2. 关键注意事项
- JobExecutionContext的修改会自动持久化(默认到数据库),后续步骤可通过
@Value("#{jobExecutionContext['aa']}")读取更新后的值。 - 避免在ItemReader中频繁修改上下文,Reader可能在重启场景下被重复调用,易导致数据不一致。
二、补充问题解答:@StepScope组件的上下文传递方式
使用@StepScope的ItemWriter/ItemReader/ItemProcessor不是只能通过构造注入传递上下文,有多种实现方式:
直接注入StepExecution/JobExecution
在Bean方法或组件构造器中注入对象,直接操作上下文:@StepScope @Bean public ItemWriter<Bar> customItemWriter(StepExecution stepExecution) { return items -> { // 读取上下文数据 String value = stepExecution.getJobExecution().getExecutionContext().getString("aa"); // 业务写入逻辑 }; }@Value表达式只读读取
针对无需修改的场景,用SpEL表达式直接读取上下文值:@StepScope @Bean public ItemProcessor<Foo, Bar> customItemProcessor(@Value("#{jobExecutionContext['input.name']}") String inputName) { return item -> { // 使用读取到的inputName处理业务 return new Bar(item, inputName); }; }实现StepExecutionListener接口
如第一部分示例,通过监听器方法获取StepExecution,在组件生命周期中处理上下文,适合需要在步骤前后操作上下文的场景。
内容的提问来源于stack exchange,提问作者gfan
相关产品推荐
相关产品推荐

