Spring中的Async注解

251 阅读4分钟

一,使用

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Async {
   //指定异步执行的线程池
   String value() default "";
}

1,作用与方法上

2,作用与类上

二,实现原理

1,启动类添加@EnableAysnc注解

@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync

该注解通过Import注解引入AsyncConfigurationSelector类

2,AsyncConfigurationSelector类

继承体系 AsyncConfigurationSelector.png

3,ImportSelector接口

作用:实现类根据给定的选择标准(通常是一个或多个注释属性)确定应该导入哪些配置类。

public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
   @Override
   @Nullable
   //EnableAsync#mode()属性PROXY/ASPECTJ返回不同的配置类
   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;
      }
   }
}
public abstract class AdviceModeImportSelector<A extends Annotation> implements ImportSelector {

   public static final String DEFAULT_ADVICE_MODE_ATTRIBUTE_NAME = "mode";

   protected String getAdviceModeAttributeName() {
      return DEFAULT_ADVICE_MODE_ATTRIBUTE_NAME;
   }

   @Override
   public final String[] selectImports(AnnotationMetadata importingClassMetadata) {
   //获取EnableAsync注解
      Class<?> annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class);
      //获取注解值
      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 = attributes.getEnum(getAdviceModeAttributeName());
      //根据类型获取特定配置类
      String[] imports = selectImports(adviceMode);
      if (imports == null) {
         throw new IllegalArgumentException("Unknown AdviceMode: " + adviceMode);
      }
      return imports;
   }
   //模板方法
   @Nullable
   protected abstract String[] selectImports(AdviceMode adviceMode);
}

4,ProxyAsyncConfiguration类

配置类注册AsyncAnnotationBeanPostProcessor

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {

   @Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
      Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
      //注册AsyncAnnotationBeanPostProcessor
      AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
      bpp.configure(this.executor, this.exceptionHandler);
      Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
      if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
         bpp.setAsyncAnnotationType(customAsyncAnnotation);
      }
      bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
      bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
      return bpp;
   }

}

5,AsyncAnnotationBeanPostProcessor类

BeanPostProcessor接口实现类 AsyncAnnotationBeanPostProcessor.png

public class AsyncAnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor {

   public void configure(
         @Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {

      this.executor = executor;
      this.exceptionHandler = exceptionHandler;
   }

   @Override
   public void setBeanFactory(BeanFactory beanFactory) {
      super.setBeanFactory(beanFactory);
      //设置切面
      //AsyncAnnotationAdvisor将方法的执行交给Exector执行
      AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
      if (this.asyncAnnotationType != null) {
         advisor.setAsyncAnnotationType(this.asyncAnnotationType);
      }
      advisor.setBeanFactory(beanFactory);
      this.advisor = advisor;
   }

}
public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {

   private Advice advice;

   private Pointcut pointcut;

   protected Advice buildAdvice(
         @Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
      //通知
      AnnotationAsyncExecutionInterceptor interceptor = new AnnotationAsyncExecutionInterceptor(null);
      interceptor.configure(executor, exceptionHandler);
      return interceptor;
   }
   //切点
   protected Pointcut buildPointcut(Set<Class<? extends Annotation>> asyncAnnotationTypes) {
      ComposablePointcut result = null;
      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);
   }

}
public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSupport implements BeanPostProcessor {
   //关键方法,Bean初始化之后进行该逻辑
   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) {
      if (this.advisor == null || bean instanceof AopInfrastructureBean) {
         // Ignore AOP infrastructure such as scoped proxies.
         return bean;
      }

      if (bean instanceof Advised) {
         Advised advised = (Advised) bean;
         if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
            // 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;
         }
      }

      if (isEligible(bean, beanName)) {
         ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
         if (!proxyFactory.isProxyTargetClass()) {
            evaluateProxyInterfaces(bean.getClass(), proxyFactory);
         }
         proxyFactory.addAdvisor(this.advisor);
         customizeProxyFactory(proxyFactory);
         //生成代理对象
         return proxyFactory.getProxy(getProxyClassLoader());
      }

      // No proxy needed.
      return bean;
   }

}

6,AsyncExecutionInterceptor

public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport implements MethodInterceptor, Ordered {
   //核心方法
   @Override
   @Nullable
   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任务
      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());
   }
}

7,AsyncExecutionAspectSupport

public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
   //确定异步执行器
   @Nullable
   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;
         }
         executor = (targetExecutor instanceof AsyncListenableTaskExecutor ?
               (AsyncListenableTaskExecutor) targetExecutor : new TaskExecutorAdapter(targetExecutor));
         this.executors.put(method, executor);
      }
      return executor;
   }

   @Nullable
   protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {
      if (beanFactory != 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.
            return beanFactory.getBean(TaskExecutor.class);
         }
         catch (NoUniqueBeanDefinitionException ex) {
            logger.debug("Could not find unique TaskExecutor bean", ex);
            try {
               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 {
               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;
   }
   //提交
   @Nullable
   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;
      }
   }

}

# 总结与启示

启动阶段,通过@EnableAsync注解导入配置类AsyncConfigurationSelector,最终实例化一个异步注解的后置处理器(AsyncAnnotationBeanPostProcessor),这个后置处理器有自己的切入点和处理逻辑AnnotationAsyncExecutionInterceptor,会拦截项目中所有的bean,如果某个bean符合该后置处理器的切入点,那么SpringBoot会通过AOP生成一个代理对象,生成代理对象时会设置一个回调,回调的内容就是后置处理器中的处理逻辑(实际逻辑就是将异步方法内容放入线程池中执行),并将这个代理对象注入到使用的地方。当真正调用异步方法时,因为注入的是代理对象,那么调用到异步方法之前会进入之前设置的回调,去执行异步方法内容,执行完毕后会根据不同的返回值类型处理返回值,至此异步方法就执行完毕了。