TaskExecutor和TaskScheduler被Spring选为同一类型

时间:2013-12-11 00:33:03

标签: java spring

我有以下配置:

@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的两种可能类型?

1 个答案:

答案 0 :(得分:4)

这个@Bean方法

@Bean
public TaskScheduler taskScheduler() {

返回ThreadPoolTaskScheduler类型的对象,即

public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
    implements TaskScheduler, SchedulingTaskExecutor {

所以它适合两个接口,TaskSchedulerTaskExecutor(超级类型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类型来满足注入目标。