自定义StepScope Bean后,Java Config中如何传递JobParameters?
咱们先拆解下你遇到的问题:你之前因为Scope 'step' is not active的错误手动定义了StepScope Bean,结果反而导致jobParameters无法被SpEL表达式解析,抛出'jobParameters' cannot be found的异常。核心原因其实是你手动注册的StepScope破坏了Spring Batch自动配置的上下文。
问题根源
@EnableBatchProcessing注解已经帮我们自动注册了StepScope和JobScope这两个作用域Bean,并且默认配置好了必要的属性(比如autoProxy = true)。当你手动定义一个同类型的StepScope Bean时,会覆盖自动配置的实例,导致StepScope的上下文没有正确绑定JobExecution相关的变量(比如jobParameters),所以SpEL表达式没法找到jobParameters对象。
具体解决方案
1. 移除手动定义的StepScope Bean
直接删掉这段代码,让@EnableBatchProcessing的自动配置来管理StepScope:
// 删掉这段手动定义的代码 @Bean @Qualifier("stepScope") public org.springframework.batch.core.scope.StepScope stepScope() { final org.springframework.batch.core.scope.StepScope stepScope = new org.springframework.batch.core.scope.StepScope(); stepScope.setAutoProxy(true); return stepScope; }
2. 修正代码中的拼写错误
看你提供的代码里,partitionStep方法中有个拼写错误:gridZize应该是gridSize(变量名少了个S),这个错误会导致运行时找不到变量,必须修正。
3. 确保@StepScope注解正确使用
你的partitionStep和slaveStep已经标注了@StepScope,这部分是正确的。修正后的完整配置示例如下:
@Configuration @EnableBatchProcessing public class MyConfig{ @Bean @Qualifier("partitionJob") public Job partitionJob() throws Exception { return jobBuilderFactory .get("partitionJob") .incrementer(new RunIdIncrementer()) .start(partitionStep(null)) // 这里传null是因为StepScope会在运行时注入实际值 .build(); } @Bean @StepScope public Step partitionStep( @Value("#{jobParameters[gridSize]}") String gridSize) throws Exception { // 修正拼写错误:gridZize -> gridSize,同时转成int类型适配gridSize方法参数 return stepBuilderFactory .get("partitionStep") .partitioner("slaveStep", partitioner()) .gridSize(Integer.parseInt(gridSize)) .step(slaveStep(null)) .taskExecutor(threadPoolTaskExecutor()) .build(); } @Bean @StepScope public Step slaveStep(@Value("#{jobParameters[chunkSize]}") int chunkSize) throws Exception { return stepBuilderFactory .get("slaveStep") // 补充你的step核心逻辑,比如reader/writer/processor .<YourInputType, YourOutputType>chunk(chunkSize) .reader(yourItemReader()) .processor(yourItemProcessor()) .writer(yourItemWriter()) .build(); } // 补充你需要的其他依赖Bean示例 @Bean public Partitioner partitioner() { // 实现你的分区逻辑 return new YourCustomPartitioner(); } @Bean public TaskExecutor threadPoolTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(20); executor.initialize(); return executor; } }
额外说明
如果你确实需要自定义StepScope的属性(比如调整代理模式、作用域缓存等),不要手动注册Bean,而是通过实现BatchConfigurer接口或者给自定义StepScope Bean加上@Primary注解确保优先级。不过绝大多数场景下,@EnableBatchProcessing的默认配置完全够用,不需要额外自定义。
这样调整后,StepScope的上下文会正确绑定JobExecution的变量,jobParameters就能被SpEL表达式正常解析了。
内容的提问来源于stack exchange,提问作者DBreaker

