概述
AsyncAnnotationBeanPostProcessor是一个AbstractBeanFactoryAwareAdvisingPostProcessor/BeanPostProcessor,它在容器启动时被使用,检测每个bean是否符合在类级别或者方法级别使用异步注解,如果使用了,则会使用一个AsyncAnnotationAdvisor包裹该bean,从而该bean上通过异步注解所定义的方法在调用时会被真正地异步调用起来。
上面所提到的"异步注解"可以通过AsyncAnnotationBeanPostProcessor指定,如果不指定,则缺省是指Spring @Async注解和EJB 3.1 javax.ejb.Asynchronous注解。
另外在真正执行异步调用的方面,可以为AsyncAnnotationBeanPostProcessor指定一个任务执行器TaskExecutor,如果不指定,AsyncAnnotationBeanPostProcessor会这么决定一个任务执行器:
- 如果容器中存在唯一的一个
TaskExecutor bean则使用它; - 否则从容器中查找名字为
taskExecutor类型为Executor的bean; - 再不然,就自己创建一个
SimpleAsyncTaskExecutor使用。
以上该逻辑,可以参考类源代码
AsyncExecutionInterceptor。
在异步执行的异常处理方面,AsyncAnnotationBeanPostProcessor也做了考虑。方法调用的异步执行根据返回结果类型分两种情况:
- 返回结果类型为
void - 返回结果类型为
Future
对于返回结果类型为Future的情况,不用做任何设置,调用者就可以使用try-catch机制捕捉异步执行产生的异常。而对于返回结果类型为void的情况,Spring支持设置一个AsyncUncaughtExceptionHandler来支持调用者处理其中发生的异常。这个AsyncUncaughtExceptionHandler可以通过AsyncAnnotationBeanPostProcessor来设置。
另外AsyncAnnotationBeanPostProcessor会将AsyncAnnotationAdvisor包裹到代理对象的最外面,也就是在调用链中会被优先调用到。
关于AsyncAnnotationBeanPostProcessor的使用,可以参考如下类 :
- 注解
@EnableAsync– 导入了AsyncConfigurationSelector AsyncConfigurationSelector– 导入了ProxyAsyncConfigurationProxyAsyncConfiguration– 使用AsyncAnnotationBeanPostProcessor定义基础设施bean asyncAdvisor
源代码
源代码版本 : spring-context-5.1.5.RELEASE
package org.springframework.scheduling.annotation;
import java.lang.annotation.Annotation;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.autoproxy.AbstractBeanFactoryAwareAdvisingPostProcessor;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.task.TaskExecutor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.function.SingletonSupplier;
/**
* Bean post-processor that automatically applies asynchronous invocation
* behavior to any bean that carries the @Async annotation at class or
* method-level by adding a corresponding AsyncAnnotationAdvisor to the
* exposed proxy (either an existing AOP proxy or a newly generated proxy that
* implements all of the target's interfaces).
*
* The TaskExecutor responsible for the asynchronous execution may
* be provided as well as the annotation type that indicates a method should be
* invoked asynchronously. If no annotation type is specified, this post-
* processor will detect both Spring's Async @Async annotation as well
* as the EJB 3.1 javax.ejb.Asynchronous annotation.
*
* For methods having a void return type, any exception thrown
* during the asynchronous method invocation cannot be accessed by the
* caller. An AsyncUncaughtExceptionHandler can be specified to handle
* these cases.
*
* Note: The underlying async advisor applies before existing advisors by default,
* in order to switch to async execution as early as possible in the invocation chain.
*
* @author Mark Fisher
* @author Juergen Hoeller
* @author Stephane Nicoll
* @since 3.0
* @see Async
* @see AsyncAnnotationAdvisor
* @see #setBeforeExistingAdvisors
* @see ScheduledAnnotationBeanPostProcessor
*/
@SuppressWarnings("serial")
public class AsyncAnnotationBeanPostProcessor
extends AbstractBeanFactoryAwareAdvisingPostProcessor {
/**
* The default name of the TaskExecutor bean to pick up: "taskExecutor".
* Note that the initial lookup happens by type; this is just the fallback
* in case of multiple executor beans found in the context.
* @since 4.2
* @see AnnotationAsyncExecutionInterceptor#DEFAULT_TASK_EXECUTOR_BEAN_NAME
*/
public static final String DEFAULT_TASK_EXECUTOR_BEAN_NAME =
AnnotationAsyncExecutionInterceptor.DEFAULT_TASK_EXECUTOR_BEAN_NAME;
protected final Log logger = LogFactory.getLog(getClass());
// 用于记录外部指定的执行器
@Nullable
private Supplier<Executor> executor;
// 用于记录外部指定的异常处理器
@Nullable
private Supplier<AsyncUncaughtExceptionHandler> exceptionHandler;
// 用于记录外部指定的异步注解类型
@Nullable
private Class<? extends Annotation> asyncAnnotationType;
public AsyncAnnotationBeanPostProcessor() {
// 设置将自己的 Advisor 包裹到已存在 Advisor 的外面,也就是设置为拦截器调用链中的高优先级
setBeforeExistingAdvisors(true);
}
/**
* Configure this post-processor with the given executor and exception handler suppliers,
* applying the corresponding default if a supplier is not resolvable.
* @since 5.1
*/
public void configure(
@Nullable Supplier<Executor> executor,
@Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
this.executor = executor;
this.exceptionHandler = exceptionHandler;
}
/**
* Set the Executor to use when invoking methods asynchronously.
* If not specified, default executor resolution will apply: searching for a
* unique TaskExecutor bean in the context, or for an Executor
* bean named "taskExecutor" otherwise. If neither of the two is resolvable,
* a local default executor will be created within the interceptor.
* @see AnnotationAsyncExecutionInterceptor#getDefaultExecutor(BeanFactory)
* @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME
*/
public void setExecutor(Executor executor) {
this.executor = SingletonSupplier.of(executor);
}
/**
* Set the AsyncUncaughtExceptionHandler to use to handle uncaught
* exceptions thrown by asynchronous method executions.
* @since 4.1
*/
public void setExceptionHandler(AsyncUncaughtExceptionHandler exceptionHandler) {
this.exceptionHandler = SingletonSupplier.of(exceptionHandler);
}
/**
* Set the 'async' annotation type to be detected at either class or method
* level. By default, both the @Async annotation and the EJB 3.1
* javax.ejb.Asynchronous annotation will be detected.
* This setter property exists so that developers can provide their own
* (non-Spring-specific) annotation type to indicate that a method (or all
* methods of a given class) should be invoked asynchronously.
* @param asyncAnnotationType the desired annotation type
*/
public void setAsyncAnnotationType(Class<? extends Annotation> asyncAnnotationType) {
Assert.notNull(asyncAnnotationType, "'asyncAnnotationType' must not be null");
this.asyncAnnotationType = asyncAnnotationType;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
// 创建自己将要包括到符合条件的bean上的Advisor
AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor,
this.exceptionHandler);
if (this.asyncAnnotationType != null) {
advisor.setAsyncAnnotationType(this.asyncAnnotationType);
}
advisor.setBeanFactory(beanFactory);
this.advisor = advisor;
}
}
Spring框架中的异步注解处理
本文介绍了Spring框架中的AsyncAnnotationBeanPostProcessor类,它用于处理类或方法级别的异步注解,确保异步方法的正确执行。当检测到@Async注解时,它会使用任务执行器来实现异步调用。默认情况下,它会查找或创建一个SimpleAsyncTaskExecutor。异常处理方面,返回void的方法异常可通过Future捕获,其他返回类型可配置AsyncUncaughtExceptionHandler。AsyncAnnotationBeanPostProcessor还会将目标对象包装在代理中。文章提供了相关类和注解的引用。
488

被折叠的 条评论
为什么被折叠?



