简体   繁体   中英

TaskExecutor and TaskScheduler being picked up by Spring as same type

I have the following configuration:

@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;
    }

}

Then I have a class listening for ContextRefreshEvents, like:

@Component
public class ScreenerScheduler implements ApplicationListener<ContextRefreshedEvent> {

    @Inject
    private TaskScheduler scheduler;

    @Inject
    private ApplicationContext context;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
}

When I run the application (web) I get:

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

Anyone could help figuring out why spring see two possible types for a TaskScheuler?

This @Bean method

@Bean
public TaskScheduler taskScheduler() {

returns an object of type ThreadPoolTaskScheduler which is

public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
    implements TaskScheduler, SchedulingTaskExecutor {

so it fits both interfaces, TaskScheduler and TaskExecutor (super type of SchedulingTaskExecutor ).

If you try to inject a field of type TaskExecutor like your stack trace says

Could not autowire field: private org.springframework.core.task.TaskExecutor...

Spring won't be able to choose which one.

This will only happen if the ApplicationContext from where you are trying to pull the beans has already initialized the beans, for example, in a Web application where your root context would register MyConfiguration and where the servlet context would declare your screenerJobExecutor bean that needs to be injected with a bean of type TaskExecutor .

You can indeed use

@Qualifier(value = "taskExecutor")

to fix this particular situation as Spring will use the bean name and not the bean type to satisfy the injection target.

it helped me

@Bean(name = "taskExecutor")
public TaskExecutor taskExecutor() {
    return new SimpleAsyncTaskExecutor();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM