Reputation: 86747
I want spring to load the default ThreadPoolTaskExecutor
from TaskExecutionAutoConfiguration
. Though I want to provide may own additional executor for some explicit side-tasks:
@Bean
public ThreadPoolExecutor myRequestPool() {
return (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
}
Problem: adding the bean above, the TaskExecutionAutoConfiguration
will not be executed anymore, and the spring-default executor will not be initialized, because @ConditionalOnMissingBean(Executor.class)
does not match anymore:
package org.springframework.boot.autoconfigure.task;
public class TaskExecutionAutoConfiguration {
@Lazy
@Bean(name = APPLICATION_TASK_EXECUTOR_BEAN_NAME)
@ConditionalOnMissingBean(Executor.class)
public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {
return builder.build();
}
Question: how can I still let spring create both beans?
Upvotes: 4
Views: 4588
Reputation: 86747
Important: Without the following "hack", Springs default behavior here is to simply hard replace the default executor with your custom one. And as a result, also execute any normal @Async
methods with your custom executor. This may mostly have undesired results.
The solution is to provide the default applicationTaskExecutor
explicit, like in TaskExecutionAutoConfiguration
. But without the @ConditionalOnMissingBean
annotation, as follows:
@Configuration
public class AppConfig {
@Lazy
@Bean(name = { TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME,
AsyncAnnotationBeanPostProcessor.DEFAULT_TASK_EXECUTOR_BEAN_NAME })
public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {
return builder.build();
}
}
This way, the default executor is always loaded, and additional custom executors can be added to the application without replacing it (which is the default behavior).
As a result, all @Async
methods will still execute with the default applicationTaskExecutor
, and all @Async("customExecutor")
will use your custom one.
Upvotes: 1
Reputation: 90457
The executor bean in TaskExecutionAutoConfiguration
will only be created if no other executor beans exist (due to @ConditionalOnMissingBean(Executor.class)
) at the moment when processing that auto-configuration . So , in order to create both of our executor and the one defined in TaskExecutionAutoConfiguration
, we need to make sure our bean is processed after TaskExecutionAutoConfiguration
According to docs , if we make our bean to be the auto-configuration candidates (which requires adding the @Configuration
class in META-INF/spring.factories
), we can then use @AutoConfigureAfter
to configure it to be processed after TaskExecutionAutoConfiguration
:
package foo.bar.baz.qux;
@Configuration
@AutoConfigureAfter(TaskExecutionAutoConfiguration.class)
public class Config {
@Bean
public ThreadPoolExecutor myRequestPool() {
return (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
}
}
Then create META-INF/spring.factories
which contains :
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
foo.bar.baz.qux.Config
Upvotes: 5