@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {
// 自定义类/方法上的开启异步功能的注解类型
// 默认支持@Async/@javax.ejb.Asynchronous,自定义后则不支持默认
Class<? extends Annotation> annotation() default Annotation.class;
// interface-based(false) or subclass-based(true)
boolean proxyTargetClass() default false;
// 代理模式,支持PROXY/ASPECTJ
AdviceMode mode() default AdviceMode.PROXY;
int order() default Ordered.LOWEST_PRECEDENCE;
}
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Async {
// 指定执行器,写入执行器BeanName即可采用指定执行器去异步执行方法
String value() default "";
}
配合@Configuration
使用,表示开启注解驱动的异步处理;
@Configuration
@EnableAsync
public class AppConfig {
}
默认地,Spring会搜索一个执行器实例用于实现异步执行方法,从以下类型中选择一个:
org.springframework.core.task.TaskExecutor
实例;java.util.concurrent.Executor
实例;org.springframework.core.task.SimpleAsyncTaskExecutor
实例处理异步方法调用;org.springframework.scheduling.annotation.AsyncConfigurer
来提供自定义java.util.concurrent.Executor
和org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler
实现;@Configuration
@EnableAsync
public class AppConfig implements AsyncConfigurer {
// 提供自定义执行器
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(7);
executor.setMaxPoolSize(42);
executor.setQueueCapacity(11);
executor.setThreadNamePrefix("MyExecutor-");
executor.initialize();
return executor;
}
// 提供自定义异常处理器
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new MyAsyncUncaughtExceptionHandler();
}
}
如果只想自定义java.util.concurrent.Executor
或者org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler
,其它方法可以直接返回null,从而保持默认配置,此时可以考虑继承org.springframework.scheduling.annotation.AsyncConfigurerSupport
;
也可以定义多个执行器,在需要异步执行的方法上通过@Async
注解value属性指定具体执行器的BeanName;
@Configuration
@EnableAsync
public class AsyncConfig {
// 自定义执行器
@Bean(name = "myExecutor")
public Executor myExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(4);
executor.setMaxPoolSize(8);
executor.setQueueCapacity(100);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("EXECUTOR");
executor.initialize();
return executor;
}
}
public class Demo {
// 指定具体执行器
@Async(value = "myExecutor")
public void method() {
// do something
}
}
@EnableAsync
注解通过Import机制引入AsyncConfigurationSelector
;
@Import(AsyncConfigurationSelector.class)
AsyncConfigurationSelector
继承自AdviceModeImportSelector
,AdviceModeImportSelector
实现支持AdviceMode
算法模板,且支持通用的@EnableXxx
注解模式,代码如下:
public final String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 获取本类支持的注解类型
// 对于AsyncConfigurationSelector来说为EnableAsync
Class<?> annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class);
Assert.state(annType != null, "Unresolvable type argument for AdviceModeImportSelector");
// 获取注解属性数据
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (attributes == null) {
throw new IllegalArgumentException(String.format(
"@%s is not present on importing class '%s' as expected",
annType.getSimpleName(), importingClassMetadata.getClassName()));
}
// 获取注解的AdviceMode属性值
AdviceMode adviceMode = attributes.getEnum(this.getAdviceModeAttributeName());
// 根据AdviceMode获取引入配置类信息
// 该方法由子类实现算法细节
String[] imports = selectImports(adviceMode);
if (imports == null) {
throw new IllegalArgumentException(String.format("Unknown AdviceMode: '%s'", adviceMode));
}
return imports;
}
@Nullable
protected abstract String[] selectImports(AdviceMode adviceMode);
AsyncConfigurationSelector
实现了算法细节selectImports
,代码如下:
public String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] { ProxyAsyncConfiguration.class.getName() };
case ASPECTJ:
return new String[] { ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME };
default:
return null;
}
}
@EnableAsync
的mode属性默认AdviceMode.PROXY
,即引入了ProxyAsyncConfiguration
;
ProxyAsyncConfiguration
继承自AbstractAsyncConfiguration
,是一个配置类,其父类AbstractAsyncConfiguration
实现了接口ImportAware
,会注入@EnableAsync
注解属性数据,且通过@Autowired
注解注入AsyncConfigurer
信息,代码如下:
public void setImportMetadata(AnnotationMetadata importMetadata) {
// 注入@EnableAsync注解的属性数据
this.enableAsync = AnnotationAttributes.fromMap(
importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false));
if (this.enableAsync == null) {
throw new IllegalArgumentException(
"@EnableAsync is not present on importing class " + importMetadata.getClassName());
}
}
/**
* Collect any {@link AsyncConfigurer} beans through autowiring.
*/
@Autowired(required = false)
void setConfigurers(Collection<AsyncConfigurer> configurers) {
if (CollectionUtils.isEmpty(configurers)) {
return;
}
// AsyncConfigurer bean只能存在一个
if (configurers.size() > 1) {
throw new IllegalStateException("Only one AsyncConfigurer may exist");
}
// 注入异步执行器和异常处理器
AsyncConfigurer configurer = configurers.iterator().next();
this.executor = configurer.getAsyncExecutor();
this.exceptionHandler = configurer.getAsyncUncaughtExceptionHandler();
}
ProxyAsyncConfiguration
配置AsyncAnnotationBeanPostProcessor
Bean,代码如下:
@Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
// 校验@EnableAsync注解属性数据
Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
// 获取开启异步功能的注解类型
Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
// 如果不是默认值,则使用自定义的值
bpp.setAsyncAnnotationType(customAsyncAnnotation);
}
if (this.executor != null) {
// 如果自定义执行器,则优先使用
bpp.setExecutor(this.executor);
}
if (this.exceptionHandler != null) {
// 如果自定义异常处理器,则优先使用
bpp.setExceptionHandler(this.exceptionHandler);
}
bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
return bpp;
}
@EnableAsync
注解最终引入了Bean后置处理器AsyncAnnotationBeanPostProcessor
,毫无疑问,它会处理带有引发异步处理的注解(如:@Async
)的Bean;
在AsyncAnnotationBeanPostProcessor
的继承层次中,AbstractAdvisingBeanPostProcessor
实现了通用的Bean后置处理,代码如下:
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof AopInfrastructureBean || this.advisor == null) {
// Ignore AOP infrastructure such as scoped proxies.
return bean;
}
// 判断Bean是否已经被代理
if (bean instanceof Advised) {
// 已经被代理,则无需为其创建代理,直接添加Advisor
Advised advised = (Advised) bean;
// 判断当前Bean是否冻结,且合格
if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
// 满足要求后,则添加Advisor,即AsyncAnnotationAdvisor
// Add our local Advisor to the existing proxy's Advisor chain...
if (this.beforeExistingAdvisors) {
advised.addAdvisor(0, this.advisor);
}
else {
advised.addAdvisor(this.advisor);
}
return bean;
}
}
// 判断Bean是否合格
if (isEligible(bean, beanName)) {
// 合格则代理该Bean
ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
if (!proxyFactory.isProxyTargetClass()) {
evaluateProxyInterfaces(bean.getClass(), proxyFactory);
}
// 应用Advisor
proxyFactory.addAdvisor(this.advisor);
customizeProxyFactory(proxyFactory);
return proxyFactory.getProxy(getProxyClassLoader());
}
// No async proxy needed.
return bean;
}
protected boolean isEligible(Object bean, String beanName) {
return isEligible(bean.getClass());
}
protected boolean isEligible(Class<?> targetClass) {
// 如果有缓存的结果,则直接使用
Boolean eligible = this.eligibleBeans.get(targetClass);
if (eligible != null) {
return eligible;
}
// 如果当前不存在Advisor则无需代理
if (this.advisor == null) {
return false;
}
// 当前的Advisor是否可以切入该targetClass
eligible = AopUtils.canApply(this.advisor, targetClass);
// 缓存结果,方便下次直接使用
this.eligibleBeans.put(targetClass, eligible);
return eligible;
}
AsyncAnnotationBeanPostProcessor
会根据开启异步功能的注解类型、异步执行器、异常处理器生成切面AsyncAnnotationAdvisor
,代码如下:
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
if (this.asyncAnnotationType != null) {
// 存在自定义的注解类型,则设置
advisor.setAsyncAnnotationType(this.asyncAnnotationType);
}
advisor.setBeanFactory(beanFactory);
this.advisor = advisor;
}
AsyncAnnotationAdvisor
是一个PointcutAdvisor
,且持有的Pointcut
为聚合了AnnotationMatchingPointcut
的ComposablePointcut
,由此看出该切面用于处理注解;
public AsyncAnnotationAdvisor(@Nullable Executor executor, @Nullable AsyncUncaughtExceptionHandler exceptionHandler) {
// 默认支持Async和javax.ejb.Asynchronous,故size为2
Set<Class<? extends Annotation>> asyncAnnotationTypes = new LinkedHashSet<>(2);
asyncAnnotationTypes.add(Async.class);
try {
asyncAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.ejb.Asynchronous", AsyncAnnotationAdvisor.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
// If EJB 3.1 API not present, simply ignore.
}
if (exceptionHandler != null) {
// 设置自定义异常处理器,若存在的话
this.exceptionHandler = exceptionHandler;
}
else {
// 使用默认异常处理器SimpleAsyncUncaughtExceptionHandler
this.exceptionHandler = new SimpleAsyncUncaughtExceptionHandler();
}
// 根据异步执行器和异常处理器生成Advice
this.advice = buildAdvice(executor, this.exceptionHandler);
// 生成Pointcut
this.pointcut = buildPointcut(asyncAnnotationTypes);
}
public void setAsyncAnnotationType(Class<? extends Annotation> asyncAnnotationType) {
Assert.notNull(asyncAnnotationType, "'asyncAnnotationType' must not be null");
Set<Class<? extends Annotation>> asyncAnnotationTypes = new HashSet<>();
asyncAnnotationTypes.add(asyncAnnotationType);
// 重新生成Pointcut
this.pointcut = buildPointcut(asyncAnnotationTypes);
}
protected Advice buildAdvice(@Nullable Executor executor, AsyncUncaughtExceptionHandler exceptionHandler) {
// 使用AnnotationAsyncExecutionInterceptor
return new AnnotationAsyncExecutionInterceptor(executor, exceptionHandler);
}
protected Pointcut buildPointcut(Set<Class<? extends Annotation>> asyncAnnotationTypes) {
ComposablePointcut result = null;
// 遍历注解类型集合,得到一个ComposablePointcut
for (Class<? extends Annotation> asyncAnnotationType : asyncAnnotationTypes) {
// 匹配类,忽略方法(MethodMatcher.TRUE)
Pointcut cpc = new AnnotationMatchingPointcut(asyncAnnotationType, true);
// 匹配方法,忽略类(ClassFilter.TRUE)
Pointcut mpc = new AnnotationMatchingPointcut(null, asyncAnnotationType, true);
if (result == null) {
result = new ComposablePointcut(cpc);
}
else {
result.union(cpc);
}
result = result.union(mpc);
}
// 若不存在注解类型,则认为全匹配
return (result != null ? result : Pointcut.TRUE);
}
至此可知,AsyncAnnotationBeanPostProcessor
通过组合AnnotationMatchingPointcut
的ComposablePointcut
判断是否可以将AsyncAnnotationAdvisor
切入到Bean中,然后通过AnnotationAsyncExecutionInterceptor
进行增强处理;
AnnotationAsyncExecutionInterceptor
继承自AsyncExecutionAspectSupport
,且实现了MethodInterceptor
;
AsyncExecutionAspectSupport
实现了异步执行器的处理,代码如下:
protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
// 从缓存的信息中找到该Method对应的异步执行器
AsyncTaskExecutor executor = this.executors.get(method);
if (executor == null) {
// 若未缓存,则需要解析对应的执行器
Executor targetExecutor;
// 获取执行器的合格者描述,若存在的话
// 即@Async注解的value属性值
String qualifier = getExecutorQualifier(method);
if (StringUtils.hasLength(qualifier)) {
// 若存在,则根据qualifier查找执行器
targetExecutor = findQualifiedExecutor(this.beanFactory, qualifier);
}
else {
// 不存在,则使用自定义的执行器
targetExecutor = this.defaultExecutor;
if (targetExecutor == null) {
synchronized (this.executors) {
if (this.defaultExecutor == null) {
// 无自定义的执行器,则获取默认的执行器
this.defaultExecutor = getDefaultExecutor(this.beanFactory);
}
targetExecutor = this.defaultExecutor;
}
}
}
if (targetExecutor == null) {
// 若还找不到执行器,则直接返回null
return null;
}
// 包装targetExecutor为异步执行器
executor = (targetExecutor instanceof AsyncListenableTaskExecutor ?
(AsyncListenableTaskExecutor) targetExecutor : new TaskExecutorAdapter(targetExecutor));
// 缓存该Method的异步执行器信息,方便下次直接从缓存中获取
this.executors.put(method, executor);
}
return executor;
}
protected Executor findQualifiedExecutor(@Nullable BeanFactory beanFactory, String qualifier) {
if (beanFactory == null) {
throw new IllegalStateException("BeanFactory must be set on " + getClass().getSimpleName() +
" to access qualified executor '" + qualifier + "'");
}
// 从BeanFactory中根据指定名称qualifier查找Executor类型Bean
return BeanFactoryAnnotationUtils.qualifiedBeanOfType(beanFactory, Executor.class, qualifier);
}
protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {
if (beanFactory != null) {
try {
// 先从BeanFactory中查找唯一的TaskExecutor类型Bean
// 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.
return beanFactory.getBean(TaskExecutor.class);
}
catch (NoUniqueBeanDefinitionException ex) {
logger.debug("Could not find unique TaskExecutor bean", ex);
try {
// 若存在多个,则继续根据名称"taskExecutor"查找Executor类型Bean
return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
}
catch (NoSuchBeanDefinitionException ex2) {
if (logger.isInfoEnabled()) {
logger.info("More than one TaskExecutor bean found within the context, and none is named " +
"'taskExecutor'. Mark one of them as primary or name it 'taskExecutor' (possibly " +
"as an alias) in order to use it for async processing: " + ex.getBeanNamesFound());
}
}
}
catch (NoSuchBeanDefinitionException ex) {
logger.debug("Could not find default TaskExecutor bean", ex);
try {
// 若找不到TaskExecutor类型Bean,则继续根据名称"taskExecutor"查找Executor类型Bean
return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
}
catch (NoSuchBeanDefinitionException ex2) {
logger.info("No task executor bean found for async processing: " +
"no bean of type TaskExecutor and no bean named 'taskExecutor' either");
}
// Giving up -> either using local default executor or none at all...
}
}
return null;
}
protected Object doSubmit(Callable<Object> task, AsyncTaskExecutor executor, Class<?> returnType) {
// 根据异步任务不同的返回值类型,选择不同的执行方案
if (CompletableFuture.class.isAssignableFrom(returnType)) {
return CompletableFuture.supplyAsync(() -> {
try {
return task.call();
}
catch (Throwable ex) {
throw new CompletionException(ex);
}
}, executor);
}
else if (ListenableFuture.class.isAssignableFrom(returnType)) {
return ((AsyncListenableTaskExecutor) executor).submitListenable(task);
}
else if (Future.class.isAssignableFrom(returnType)) {
return executor.submit(task);
}
else {
executor.submit(task);
return null;
}
}
protected void handleError(Throwable ex, Method method, Object... params) throws Exception {
if (Future.class.isAssignableFrom(method.getReturnType())) {
// 如果Method返回值为Future,则rethrow异常
ReflectionUtils.rethrowException(ex);
}
else {
// Could not transmit the exception to the caller with default executor
try {
// 使用异常处理器处理异常
this.exceptionHandler.handleUncaughtException(ex, method, params);
}
catch (Throwable ex2) {
logger.error("Exception handler for async method '" + method.toGenericString() +
"' threw unexpected exception itself", ex2);
}
}
}
AsyncExecutionInterceptor
重写了getDefaultExecutor
方法,确保默认执行器存在;且实现MethodInterceptor
的invoke方法,代码如下:
protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {
Executor defaultExecutor = super.getDefaultExecutor(beanFactory);
// 当找不到默认执行器,则使用SimpleAsyncTaskExecutor
return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
}
public Object invoke(final MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// 获取最终执行的方法
Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
// 桥接方法
final Method userDeclaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
// 获取异步执行器
AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
if (executor == null) {
throw new IllegalStateException(
"No executor specified and no default executor set on AsyncExecutionInterceptor either");
}
// 创建异步任务
Callable<Object> task = () -> {
try {
// 执行调用
Object result = invocation.proceed();
if (result instanceof Future) {
// 返回结果
return ((Future<?>) result).get();
}
}
catch (ExecutionException ex) {
handleError(ex.getCause(), userDeclaredMethod, invocation.getArguments());
}
catch (Throwable ex) {
handleError(ex, userDeclaredMethod, invocation.getArguments());
}
return null;
};
// 提交异步任务
return doSubmit(task, executor, invocation.getMethod().getReturnType());
}
AsyncAnnotationBeanPostProcessor
实现了getExecutorQualifier
,从而支持@Async
注解,代码如下:
protected String getExecutorQualifier(Method method) {
// Maintainer's note: changes made here should also be made in
// AnnotationAsyncExecutionAspect#getExecutorQualifier
// 获取Method上的Async注解
Async async = AnnotatedElementUtils.findMergedAnnotation(method, Async.class);
if (async == null) {
// 获取Method所在类上的Async注解
async = AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), Async.class);
}
// 使用Async注解的value属性值,若存在的话
return (async != null ? async.value() : null);
}
原因
一般是调用同一个类中的@Async注解标注的方法,此时无法经过AOP处理,导致异步执行失效;
解决方法
在调用方法中,从Bean容器中获取本类的代理实例,使用代理实例调用@Asyc注解标注的方法;
@Autowired
private ApplicationContext applicationContext;
public void invoke() {
System.out.println("当前线程:" + Thread.currentThread().getName());
Demo demo = applicationContext.getBean(Demo.class);
demo.async();
}
@Async
public void async() {
// do something
System.out.println("当前线程:" + Thread.currentThread().getName());
}