[英]Spring: Step Scope & Bean Autowiring
我目前正处于一个我似乎无法弄清楚的问题的真正痛苦之中。 我希望这里有人可以提供一些指导。 这一切都围绕着 StepScope、bean 自动装配和 bean 创建。
(为简单起见,我减少了配置 class。)
@Configuration
@EnableBatchProcessing
public class Config {
@Bean
@StepScope
public StepScopeBeanOne stepScopeBeanOne() {
return new StepScopeBeanOne();
}
@Bean
@StepScope
public StepScopeBeanTwo stepScopeBeanTwo () {
return new StepScopeBeanTwo();
}
@Bean
@StepScope
public Processor processor() {
return new Processor();
}
}
public class Processor implements ItemProcessor<Incoming, Outgoing> {
//The two injected step scope beans...
@Autowired
private StepScopeBeanOne stepScopeBeanOne;
@Autowired
private StepScopeBeanTwo stepScopeBeanTwo;
@Override
public Outgoing process(Incoming incoming) {
//do process...
}
public void setStepScopeBeanTwo(StepScopeBeanTwo stepScopeBeanTwo) {
this.stepScopeBeanTwo = stepScopeBeanTwo;
}
public void setStepScopeBeanOne(StepScopeBeanOne stepScopeBeanOne) {
this.stepScopeBeanOne = stepScopeBeanOne;
}
//rest of class...
}
org.springframework.beans.factory.UnsatisfiedDependencyException:创建名称为“scopedTarget.scopedTarget.Processor”的bean时出错:通过字段“stepScopeBeanOne”表示不满足的依赖关系; 嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有“StepScopeBeanOne”类型的合格 bean 可用:预计至少有 1 个有资格作为自动装配候选者的 bean。 依赖注解:{@org.springframework.beans.factory.annotation.Autowired(required=true)}
我相信这与解析处理器 bean 时 bean StepScopeBeanOne 不在 ApplicationContext 中有关。
@Configuration
@EnableBatchProcessing
public class Config {
@Bean
@StepScope
public StepScopeBeanOne stepScopeBeanOne() {
return new StepScopeBeanOne();
}
@Bean
@StepScope
public StepScopeBeanTwo stepScopeBeanTwo () {
return new StepScopeBeanTwo();
}
@Bean
@StepScope
public Processor processor() {
Processor processor = new Processor();
processor.setStepScopeBeanOne(stepScopeBeanOne());
processor.setStepScopeBeanTwo(stepScopeBeanTwo());
return processor;
}
}
org.springframework.beans.factory.BeanCreationException:在 class 路径资源 [Config.class] 中定义名称为“scopedTarget.scopedTarget.Processor”的 bean 创建错误:通过工厂方法进行 Bean 实例化失败; 嵌套异常是 org.springframework.beans.BeanInstantiationException:无法实例化 [Processor]:工厂方法“处理器”抛出异常; 嵌套异常是 java.lang.IllegalStateException:@Bean 方法 Config.stepScopeBeanOne 被称为类型 [StepScopeBeanOne] 的 bean 引用,但被类型 [com.sun.proxy.$Proxy149] 的不兼容 bean 实例覆盖。 在 class 路径资源 [Config.class] 中定义的 BeanDefinition 中声明的同名覆盖 bean
我之前遇到过这个问题,我的解决方法是为我注入的类创建一个接口。
public interface StepScopeBeanOne {
//methods
}
public class StepScopeBeanOneImpl implements StepScopeBeanOne {
//methods
}
我不想再次使用 go 这条路线,因为我相信它会增加代码的复杂性。 如果有人有不同的解决方案,请分享。
从这些 bean 中删除步骤 Scope 会导致精细而漂亮的自动装配。
@Configuration
@EnableBatchProcessing
public class Config {
@Bean
public StepScopeBeanOne stepScopeBeanOne() {
return new StepScopeBeanOne();
}
@Bean
public StepScopeBeanTwo stepScopeBeanTwo () {
return new StepScopeBeanTwo();
}
@Bean
public Processor processor() {
Processor processor = new Processor();
return processor;
}
}
Beans 是通过 @Autowireing 注解注入的。
您可能会问自己,为什么不直接删除 @StepScope? 好吧,我不能。 我需要在每个这些 bean 上执行 scope 步骤,以允许正确注入 JobParameters。 我们在作业参数中使用步骤名称来提供微调的步骤配置。
我的目标是让配置一工作。 在该目标之外,将不胜感激更好地理解 Spring 中的 bean 创建。
我的目标是让配置一工作。
下面是一个基于“配置一”的完整示例:
import java.util.Arrays;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableBatchProcessing
public class MyJobConfiguration {
@Bean
@StepScope
public StepScopeBeanOne stepScopeBeanOne() {
return new StepScopeBeanOne();
}
@Bean
@StepScope
public StepScopeBeanTwo stepScopeBeanTwo () {
return new StepScopeBeanTwo();
}
@Bean
@StepScope
public Processor processor() {
return new Processor();
}
@Bean
public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) {
return jobs.get("job")
.start(steps.get("step")
.<Integer, Integer>chunk(5)
.reader(new ListItemReader<>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)))
.processor(processor())
.writer(items -> items.forEach(System.out::println))
.build())
.build();
}
public static void main(String[] args) throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(MyJobConfiguration.class);
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
Job job = context.getBean(Job.class);
jobLauncher.run(job, new JobParameters());
}
static class StepScopeBeanOne {
}
static class StepScopeBeanTwo {
}
static class Processor implements ItemProcessor<Integer, Integer> {
@Autowired
private StepScopeBeanOne stepScopeBeanOne;
@Autowired
private StepScopeBeanTwo stepScopeBeanTwo;
@Override
public Integer process(Integer item) throws Exception {
return item + 1;
}
public void setStepScopeBeanOne(StepScopeBeanOne stepScopeBeanOne) {
this.stepScopeBeanOne = stepScopeBeanOne;
}
public void setStepScopeBeanTwo(StepScopeBeanTwo stepScopeBeanTwo) {
this.stepScopeBeanTwo = stepScopeBeanTwo;
}
}
}
这将打印以下 output ,而不会出现关于步进范围 bean 或依赖注入的任何问题:
[main] WARN org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer - No datasource was provided...using a Map based JobRepository
[main] WARN org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer - No transaction manager was provided, using a ResourcelessTransactionManager
[main] INFO org.springframework.batch.core.launch.support.SimpleJobLauncher - No TaskExecutor has been set, defaulting to synchronous executor.
[main] INFO org.springframework.batch.core.launch.support.SimpleJobLauncher - Job: [SimpleJob: [name=job]] launched with the following parameters: [{}]
[main] INFO org.springframework.batch.core.job.SimpleStepHandler - Executing step: [step]
1
2
3
4
5
6
7
8
9
10
[main] INFO org.springframework.batch.core.step.AbstractStep - Step: [step] executed in 73ms
[main] INFO org.springframework.batch.core.launch.support.SimpleJobLauncher - Job: [SimpleJob: [name=job]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 119ms
@StepScope
等价于@Scope(value = "step", proxyMode = ScopedProxyMode.TARGET_CLASS)
(参见javadoc ),因此默认情况下,step-scoped beans 是基于类的代理(使用 cglib)并且不需要实现接口.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.