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.