前言AsyncAnnotationAdvisor
AnnotationAsyncExecutionInterceptor
AsyncExecutionAspectSupportAsyncExecutionInterceptorAnnotationAsyncExecutionInterceptor 总结
前言本章节主要了解 AsyncAnnotationAdvisor,不准确的描述:Advisor 可以视为 Advice + Pointcut,前者即执行的通知逻辑,后者即通知执行的切入点
关于 Advisor 等相关 Spring AOP API,可以自行了解或参考链接文章
【源码】Spring AOP 5 Advisor
AsyncAnnotationAdvisorpublic AsyncAnnotationAdvisor( @Nullable Supplierexecutor, @Nullable Supplier exceptionHandler) { Set > asyncAnnotationTypes = new linkedHashSet<>(2); // 指定对应的切点注解:@Async 和 javax.ejb.Asynchronous asyncAnnotationTypes.add(Async.class); try { asyncAnnotationTypes.add((Class extends Annotation>) ClassUtils.forName("javax.ejb.Asynchronous", AsyncAnnotationAdvisor.class.getClassLoader())); } catch (ClassNotFoundException ex) { } // 基于 executor 和 exceptionHandler 构建 Advice this.advice = buildAdvice(executor, exceptionHandler); // 基于 asyncAnnotationTypes 构建 Pointcut this.pointcut = buildPointcut(asyncAnnotationTypes); } ----------------- buildAdvice protected Advice buildAdvice( @Nullable Supplier executor, @Nullable Supplier exceptionHandler) { // 创建 AnnotationAsyncExecutionInterceptor AnnotationAsyncExecutionInterceptor interceptor = new AnnotationAsyncExecutionInterceptor(null); // 基于 executor 和 exceptionHandler 配置 interceptor.configure(executor, exceptionHandler); return interceptor; } ------------ buildPointcut protected Pointcut buildPointcut(Set > asyncAnnotationTypes) { ComposablePointcut result = null; for (Class extends Annotation> asyncAnnotationType : asyncAnnotationTypes) { // 标记在类上 Pointcut cpc = new AnnotationMatchingPointcut(asyncAnnotationType, true); // 标记在方法上 Pointcut mpc = new AnnotationMatchingPointcut(null, asyncAnnotationType, true); // 基于 ComposablePointcut 合并 if (result == null) { result = new ComposablePointcut(cpc); } else { result.union(cpc); } result = result.union(mpc); } return (result != null ? result : Pointcut.TRUE); }
在构造方法中创建对应的 Advice 和 Pointcut,分别为:
基于 executor 和 exceptionHandler 创建配置 AnnotationAsyncExecutionInterceptor,其中:executor 即调度异步方法的 Executor 执行器,exceptionHandler 负责处理调度异常Pointcut 根据注解 @Async 和 javax.ejb.Asynchronous 构造,可以标注在类和方法上,最终构造的是以上的并集 ComposablePointcut
接下来是对 AnnotationAsyncExecutionInterceptor 的具体了解
AnnotationAsyncExecutionInterceptor AsyncExecutionAspectSupport public AsyncExecutionAspectSupport(@Nullable Executor defaultExecutor, AsyncUncaughtExceptionHandler exceptionHandler) {
this.defaultExecutor = new SingletonSupplier<>(defaultExecutor, () -> getDefaultExecutor(this.beanFactory));
this.exceptionHandler = SingletonSupplier.of(exceptionHandler);
}
AsyncExecutionAspectSupport 是异步执行切面的基类,构造时允许指定默认的执行器其中 getDefaultExecutor 方法代码略,逻辑为:从容器中获取唯一的 type = TaskExecutor 或 name = taskExecutor 的 bean 实例,否则返回 null,因此我们在 部分场景 使用 Spring Async 可以直接注册 TaskExecutor 实例来充当异步方法的执行器
protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
// 缓存中获取
AsyncTaskExecutor executor = this.executors.get(method);
if (executor == null) {
Executor targetExecutor;
// 获取对应方法的执行器限定符
String qualifier = getExecutorQualifier(method);
if (StringUtils.hasLength(qualifier)) {
// 限定符不为空,则获取对应的执行器
targetExecutor = findQualifiedExecutor(this.beanFactory, qualifier);
}
else {
// 否则获取默认的执行器
targetExecutor = this.defaultExecutor.get();
}
if (targetExecutor == null) {
return null;
}
// 适配执行器为 AsyncListenableTaskExecutor
executor = (targetExecutor instanceof AsyncListenableTaskExecutor ?
(AsyncListenableTaskExecutor) targetExecutor : new TaskExecutorAdapter(targetExecutor));
this.executors.put(method, executor);
}
return executor;
}
determineAsyncExecutor 方法主要是为指定方法推断对应的 执行器 来执行,大体逻辑概括:
- 先从缓存获取,第一次肯定为空基于 getExecutorQualifier 来获取目标方法的 执行器限定符,该方法主要由子类实现,比如取自 @Async 注解的属性上述步骤获取的限定符不为空,则由方法 findQualifiedExecutor 获取对应的 执行器,通常可以理解为基于 beanName 从容器中获取否则使用默认的执行器执行器被适配成 AsyncListenableTaskExecutor 并缓存
public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport implements MethodInterceptor, Ordered {
// ...
}
AsyncExecutionInterceptor 同时也是一个 MethodInterceptor,因此通知逻辑聚焦于 invoke 方法
public Object invoke(final MethodInvocation invocation) throws Throwable {
// ...
// 获取对应方法的执行器
AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
if (executor == null) {
// ...
}
// 用 Callable 包装目标方法
Callable
- 基于方法获取对应的执行器,determineAsyncExecutor 即上文其父类定义的 模板方法将目标方法包装成 Callable 后由该执行器调度
// 获取方法的执行器限定符,未实现
protected String getExecutorQualifier(Method method) {
return null;
}
@Nullable
// 提供默认执行器 SimpleAsyncTaskExecutor
protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {
Executor defaultExecutor = super.getDefaultExecutor(beanFactory);
return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
}
该类未实现 getExecutorQualifier 方法该类提供默认执行器为 SimpleAsyncTaskExecutor 而非父类的 null AnnotationAsyncExecutionInterceptor
@Override
@Nullable
protected String getExecutorQualifier(Method method) {
// 从 @Async 注解上解析执行器限定符,即 value 属性
Async async = AnnotatedElementUtils.findMergedAnnotation(method, Async.class);
if (async == null) {
async = AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), Async.class);
}
return (async != null ? async.value() : null);
}
留给子类 AnnotationAsyncExecutionInterceptor 的任务就只有实现 getExecutorQualifier 方法了,用以获取指定方法的执行器限定符此处的实现就是获取注解 @Async 的 value 属性 总结
本文主要是了解 AsyncAnnotationAdvisor 的细节,若视为 Advisor = Advice + Pointcut,则:
对应的 Advice 为 AnnotationAsyncExecutionInterceptor对应的 Pointcut 即基于类和方法的注解(@Async javax.ejb.Asynchronous)匹配
其中,AnnotationAsyncExecutionInterceptor 主要有两个方面:
- 作为一个 AsyncExecutionAspectSupport,它实现了 getExecutorQualifier,可以从注解(@Async javax.ejb.Asynchronous)上解析执行器限定符来指定具体的执行器,否则使用默认(全局)执行器作为一个 MethodInterceptor,也是通知逻辑的实现,它将目标方法包装成 Callable 交给对应的执行器调度
至此,Spring Async 实现的核心逻辑类已了解的差不多了,下一章节会梳理基于 @EnabledAsync 引入 Spring Async 框架的整体流程
上一篇:【Spring】Spring Async 的实现原理 1 - ProxyProcessorSupport
下一篇:【Spring】Spring Async 的实现原理 3 - 整体实现流程



