我有以下配置:
@org.springframework.context.annotation.Configuration
@EnableJpaRepositories
@EnableAsync
@EnableScheduling
public class MyConfiguration {
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(50);
return executor;
}
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(10);
return scheduler;
}
}
然后我有一个类监听ContextRefreshEvents,如:
@Component
public class ScreenerScheduler implements ApplicationListener<ContextRefreshedEvent> {
@Inject
private TaskScheduler scheduler;
@Inject
private ApplicationContext context;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
}
当我运行应用程序(网络)时,我得到:
Error creating bean with name 'screenerJobExecutor': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.core.task.TaskExecutor example.workflow.ScreenerJobExecutor.executor; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.core.task.TaskExecutor] is defined: expected single matching bean but found 2: taskExecutor,taskScheduler
任何人都可以帮忙搞清楚为什么Spring会看到TaskScheuler的两种可能类型?
答案 0 :(得分:4)
这个@Bean
方法
@Bean
public TaskScheduler taskScheduler() {
返回ThreadPoolTaskScheduler
类型的对象,即
public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
implements TaskScheduler, SchedulingTaskExecutor {
所以它适合两个接口,TaskScheduler
和TaskExecutor
(超级类型SchedulingTaskExecutor
)。
如果您尝试注入类型为TaskExecutor
的字段,就像您的堆栈跟踪一样
Could not autowire field: private org.springframework.core.task.TaskExecutor...
Spring将无法选择哪一个。
只有当您尝试提取bean的ApplicationContext
已经初始化bean时才会发生这种情况,例如,在您的根上下文将注册MyConfiguration
的Web应用程序中以及servlet上下文将声明需要使用screenerJobExecutor
类型的bean注入的TaskExecutor
bean。
你确实可以使用
@Qualifier(value = "taskExecutor")
修复这种特殊情况,因为Spring将使用bean名称而不是bean类型来满足注入目标。