AsyncAnnotationBeanPostProcessor tries to find TaskExecutor by type/name
Issue: SPR-13248
This commit is contained in:
parent
fca33f53e3
commit
c3e57dd245
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -19,10 +19,15 @@ package org.springframework.scheduling.annotation;
|
|||
import java.lang.annotation.Annotation;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor;
|
||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
|
@ -54,10 +59,21 @@ import org.springframework.util.Assert;
|
|||
* @see Async
|
||||
* @see AsyncAnnotationAdvisor
|
||||
* @see #setBeforeExistingAdvisors
|
||||
* @see ScheduledAnnotationBeanPostProcessor
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AsyncAnnotationBeanPostProcessor extends AbstractAdvisingBeanPostProcessor implements BeanFactoryAware {
|
||||
|
||||
/**
|
||||
* The default name of the {@link TaskExecutor} bean to pick up: "taskExecutor".
|
||||
* <p>Note that the initial lookup happens by type; this is just the fallback
|
||||
* in case of multiple executor beans found in the context.
|
||||
*/
|
||||
public static final String DEFAULT_TASK_EXECUTOR_BEAN_NAME = "taskExecutor";
|
||||
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private Class<? extends Annotation> asyncAnnotationType;
|
||||
|
||||
private Executor executor;
|
||||
|
|
@ -100,9 +116,35 @@ public class AsyncAnnotationBeanPostProcessor extends AbstractAdvisingBeanPostPr
|
|||
this.exceptionHandler = exceptionHandler;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
|
||||
Executor executorToUse = this.executor;
|
||||
if (executorToUse == null) {
|
||||
try {
|
||||
// Search for TaskExecutor bean... not plain Executor since that would
|
||||
// match with ScheduledExecutorService as well, which is unusable for
|
||||
// our purposes here. TaskExecutor is more clearly designed for it.
|
||||
executorToUse = beanFactory.getBean(TaskExecutor.class);
|
||||
}
|
||||
catch (NoUniqueBeanDefinitionException ex) {
|
||||
try {
|
||||
executorToUse = beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, TaskExecutor.class);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex2) {
|
||||
throw new IllegalStateException("More than one TaskExecutor bean exists within the context, " +
|
||||
"and none is named 'taskExecutor'. Mark one of them as primary or name it " +
|
||||
"'taskExecutor' (possibly as an alias); or specify the AsyncConfigurer interface " +
|
||||
"and implement getAsyncExecutor() accordingly.", ex);
|
||||
}
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
logger.debug("Could not find default TaskExecutor bean", ex);
|
||||
// Giving up -> falling back to default executor within the advisor...
|
||||
}
|
||||
}
|
||||
|
||||
AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(executorToUse, this.exceptionHandler);
|
||||
if (this.asyncAnnotationType != null) {
|
||||
advisor.setAsyncAnnotationType(this.asyncAnnotationType);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,13 +82,14 @@ import org.springframework.util.StringValueResolver;
|
|||
* @see SchedulingConfigurer
|
||||
* @see org.springframework.scheduling.TaskScheduler
|
||||
* @see org.springframework.scheduling.config.ScheduledTaskRegistrar
|
||||
* @see AsyncAnnotationBeanPostProcessor
|
||||
*/
|
||||
public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor, Ordered,
|
||||
EmbeddedValueResolverAware, BeanFactoryAware, ApplicationContextAware,
|
||||
SmartInitializingSingleton, ApplicationListener<ContextRefreshedEvent>, DisposableBean {
|
||||
|
||||
/**
|
||||
* The default name of the TaskScheduler bean to pick up: "taskScheduler".
|
||||
* The default name of the {@link TaskScheduler} bean to pick up: "taskScheduler".
|
||||
* <p>Note that the initial lookup happens by type; this is just the fallback
|
||||
* in case of multiple scheduler beans found in the context.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -87,6 +87,60 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
|||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void taskExecutorByBeanType() {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
|
||||
BeanDefinition processorDefinition = new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class);
|
||||
context.registerBeanDefinition("postProcessor", processorDefinition);
|
||||
|
||||
BeanDefinition executorDefinition = new RootBeanDefinition(ThreadPoolTaskExecutor.class);
|
||||
executorDefinition.getPropertyValues().add("threadNamePrefix", "testExecutor");
|
||||
context.registerBeanDefinition("myExecutor", executorDefinition);
|
||||
|
||||
BeanDefinition targetDefinition =
|
||||
new RootBeanDefinition(AsyncAnnotationBeanPostProcessorTests.TestBean.class);
|
||||
context.registerBeanDefinition("target", targetDefinition);
|
||||
|
||||
context.refresh();
|
||||
|
||||
ITestBean testBean = context.getBean("target", ITestBean.class);
|
||||
testBean.test();
|
||||
testBean.await(3000);
|
||||
Thread asyncThread = testBean.getThread();
|
||||
assertTrue(asyncThread.getName().startsWith("testExecutor"));
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void taskExecutorByBeanName() {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
|
||||
BeanDefinition processorDefinition = new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class);
|
||||
context.registerBeanDefinition("postProcessor", processorDefinition);
|
||||
|
||||
BeanDefinition executorDefinition = new RootBeanDefinition(ThreadPoolTaskExecutor.class);
|
||||
executorDefinition.getPropertyValues().add("threadNamePrefix", "testExecutor");
|
||||
context.registerBeanDefinition("myExecutor", executorDefinition);
|
||||
|
||||
BeanDefinition executorDefinition2 = new RootBeanDefinition(ThreadPoolTaskExecutor.class);
|
||||
executorDefinition2.getPropertyValues().add("threadNamePrefix", "testExecutor2");
|
||||
context.registerBeanDefinition("taskExecutor", executorDefinition2);
|
||||
|
||||
BeanDefinition targetDefinition =
|
||||
new RootBeanDefinition(AsyncAnnotationBeanPostProcessorTests.TestBean.class);
|
||||
context.registerBeanDefinition("target", targetDefinition);
|
||||
|
||||
context.refresh();
|
||||
|
||||
ITestBean testBean = context.getBean("target", ITestBean.class);
|
||||
testBean.test();
|
||||
testBean.await(3000);
|
||||
Thread asyncThread = testBean.getThread();
|
||||
assertTrue(asyncThread.getName().startsWith("testExecutor2"));
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configuredThroughNamespace() {
|
||||
GenericXmlApplicationContext context = new GenericXmlApplicationContext();
|
||||
|
|
@ -264,6 +318,7 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class DirectExecutor implements Executor {
|
||||
|
||||
@Override
|
||||
|
|
@ -272,6 +327,7 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
static class ConfigWithExceptionHandler extends AsyncConfigurerSupport {
|
||||
|
|
@ -292,5 +348,4 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue