概述
这是一个Advisor
,用于激活使用了异步方法调用,所基于的信息是这些方法或者这些方法所在实现类/接口上所使用异步注解。至于是哪些异步注解,可以通过AsyncAnnotationAdvisor
来指定,如果不指定,缺省是指Spring
@Async
或者EJB 3.1
javax.ejb.Asynchronous
。
通过AsyncAnnotationAdvisor
可以指定异步方法调用的任务执行器Executer
和异步执行异常处理器AsyncUncaughtExceptionHandler
。
告诉AsyncAnnotationAdvisor
处理哪些异步注解,指定相应的任务执行器和异步执行异常处理器之后,AsyncAnnotationAdvisor
会生成以下产物供使用者使用 :
Pointcut
– 匹配任意一个指定的异步注解的切面AnnotationAsyncExecutionInterceptor
– 一个异步方法执行拦截器,用于被使用者包裹到符合条件的bean
上
AsyncAnnotationAdvisor
的使用参考AsyncAnnotationBeanPostProcessor
。
源代码
源代码版本 : spring-context-5.1.5.RELEASE
package org.springframework.scheduling.annotation;
// 省略 import 行
/**
* Advisor that activates asynchronous method execution through the @Async
* annotation. This annotation can be used at the method and type level in
* implementation classes as well as in service interfaces.
*
* This advisor detects the EJB 3.1 javax.ejb.Asynchronous
* annotation as well, treating it exactly like Spring's own Async.
* Furthermore, a custom async annotation type may get specified through the
* #setAsyncAnnotationType "asyncAnnotationType" property.
*
* @author Juergen Hoeller
* @since 3.0
* @see Async
* @see AnnotationAsyncExecutionInterceptor
*/
@SuppressWarnings("serial")
public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {
private Advice advice;
private Pointcut pointcut;
/**
* Create a new AsyncAnnotationAdvisor for bean-style configuration.
*/
public AsyncAnnotationAdvisor() {
this((Supplier<Executor>) null, (Supplier<AsyncUncaughtExceptionHandler>) null);
}
/**
* Create a new AsyncAnnotationAdvisor for the given task executor.
* @param executor the task executor to use for asynchronous methods
* (can be null to trigger default executor resolution)
* @param exceptionHandler the AsyncUncaughtExceptionHandler to use to
* handle unexpected exception thrown by asynchronous method executions
* @see AnnotationAsyncExecutionInterceptor#getDefaultExecutor(BeanFactory)
*/
@SuppressWarnings("unchecked")
public AsyncAnnotationAdvisor(
@Nullable Executor executor, @Nullable AsyncUncaughtExceptionHandler exceptionHandler) {
this(SingletonSupplier.ofNullable(executor), SingletonSupplier.ofNullable(exceptionHandler));
}
/**
* Create a new AsyncAnnotationAdvisor for the given task executor.
* @param executor the task executor to use for asynchronous methods
* (can be null to trigger default executor resolution)
* @param exceptionHandler the AsyncUncaughtExceptionHandler to use to
* handle unexpected exception thrown by asynchronous method executions
* @since 5.1
* @see AnnotationAsyncExecutionInterceptor#getDefaultExecutor(BeanFactory)
*/
@SuppressWarnings("unchecked")
public AsyncAnnotationAdvisor(
@Nullable Supplier<Executor> executor,
@Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
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.
}
this.advice = buildAdvice(executor, exceptionHandler);
this.pointcut = buildPointcut(asyncAnnotationTypes);
}
/**
* 设置所要解析的异步注解,如果不指定,使用缺省值 : @Async 和 EJB 3.1 javax.ejb.Asynchronous
* 都支持
* Set the 'async' annotation type.
* <p>The default async annotation type is the @Async annotation, as well
* as the EJB 3.1 javax.ejb.Asynchronous annotation (if present).
* This setter property exists so that developers can provide their own
* (non-Spring-specific) annotation type to indicate that a method is to
* be executed asynchronously.
* @param asyncAnnotationType the desired annotation type
*/
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);
this.pointcut = buildPointcut(asyncAnnotationTypes);
}
/**
* Set the {@code BeanFactory} to be used when looking up executors by qualifier.
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) {
if (this.advice instanceof BeanFactoryAware) {
((BeanFactoryAware) this.advice).setBeanFactory(beanFactory);
}
}
@Override
public Advice getAdvice() {
return this.advice;
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
// 构建 Advice, 实现类使用 AnnotationAsyncExecutionInterceptor,
// 关联了指定的执行器 executor,和异步异常处理器 exceptionHandler
protected Advice buildAdvice(
@Nullable Supplier<Executor> executor,
@Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
AnnotationAsyncExecutionInterceptor interceptor =
new AnnotationAsyncExecutionInterceptor(null);
interceptor.configure(executor, exceptionHandler);
return interceptor;
}
/**
* Calculate a pointcut for the given async annotation types, if any.
* @param asyncAnnotationTypes the async annotation types to introspect
* @return the applicable Pointcut object, or null if none
*/
protected Pointcut buildPointcut(Set<Class<? extends Annotation>> asyncAnnotationTypes) {
ComposablePointcut result = null;
// 将 asyncAnnotationTypes 中所指定的注解联合构造一个组合切面对象 ComposablePointcut
// 如果 asyncAnnotationTypes 则返回 Pointcut.TRUE, 表示比较时总是返回匹配
for (Class<? extends Annotation> asyncAnnotationType : asyncAnnotationTypes) {
Pointcut cpc = new AnnotationMatchingPointcut(asyncAnnotationType, 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);
}
}