Spring Batch:如何创建支持参数注入的Prototype Scope Reader?
解决方案:结合@StepScope与@Scope("prototype")实现通用Reader原型
可以通过**同时使用@StepScope和@Scope("prototype")**来实现兼具原型特性和Step级参数注入的Bean,核心是要正确获取原型Bean实例,避免Spring配置类方法调用的代理限制。
修正后的实现代码
@Autowired private JobExecutionDecider namespaceDecider; @Autowired protected StepBuilderFactory steps; @Autowired private ApplicationContext applicationContext; @Bean protected Flow itemFlow() { FlowBuilder<SimpleFlow> flow = new FlowBuilder<>("itemFlow"); flow.start(namespaceDecider); // 通过ApplicationContext获取不同类型的Reader原型实例 flow.from(namespaceDecider).on(V1).to(itemStep(getItemReader(Type1.class))); flow.from(namespaceDecider).on(V2).to(itemStep(getItemReader(Type2.class))); flow.from(namespaceDecider).on(V3).to(itemStep(getItemReader(Type3.class))); return flow.build(); } @Bean @Scope("prototype") protected <T extends ItemType> Step itemStep(ItemReader<? extends T> itemReader) { return steps.get("itemStep").<ItemType, Order>chunk(CHUNK_SIZE) .reader(itemReader) .processor(itemProcessor()) .writer(itemWriter()) .build(); } @Bean @StepScope @Scope("prototype") protected <T> ItemReader<T> itemReader(Class<T> claz, @Value("#{stepExecutionContext['itemMessage']}") ItemMessage itemMessage) { return xmlObjectReader(claz, itemMessage); } // 封装获取Reader实例的方法,避免直接调用配置类Bean方法 private <T> ItemReader<T> getItemReader(Class<T> clazz) { // 传递构造参数,第二个参数对应itemReader方法的itemMessage(可根据实际场景从上下文获取) return applicationContext.getBean(ItemReader.class, clazz, null); }
关键说明
注解组合使用
- 给
itemReader同时添加@StepScope和@Scope("prototype"):@StepScope确保Bean能访问Step执行上下文的参数(如stepExecutionContext中的数据);@Scope("prototype")保证每次获取Bean时创建新实例,满足不同Reader的独立需求。
- 给
正确获取原型实例
- 不能直接在
itemFlow中调用itemReader()方法:Spring会将配置类中的Bean方法调用代理为单例引用,无法触发原型实例的创建。 - 通过
ApplicationContext.getBean()方法获取实例,同时传递类型参数和注入参数,确保每次请求都生成新的Reader实例,并正确注入Step级参数。
- 不能直接在
参数注入调整
- 将
@Value("to-be-injected")改为@Value("#{stepExecutionContext['itemMessage']},表示从Step执行上下文中读取参数。你可以在JobExecutionDecider的decide方法中,将需要的itemMessage存入stepExecution.getExecutionContext()。
- 将
补充注意事项
- 确保配置类已添加
@EnableBatchProcessing注解,开启Spring Batch的StepScope支持; - 如果
itemMessage不需要默认值null,可以在Decider中提前设置好上下文参数,避免传递空值; itemStep的@Scope("prototype")注解是必要的,确保每个分支都创建独立的Step实例。
内容的提问来源于stack exchange,提问作者Daan
相关产品推荐
相关产品推荐

