spring context源码解析之@Async

一、背景

本文转自“天河聊技术”微信公众号

大家项目中用到异步、多线程的场景很多,使用最多的场景还是主动对象模式,就是主线程开启一个线程池去任务分发,任务执行完成之后,关闭线程池,但是有的场景则需要部分代码异步执行的效果,简单的说就是有一个可以复用的线程池可以复用,直接new Thread当然也可以,不推荐,没有线程池的可靠性好,如果这个时候再创建一个线程池用完再关闭代码是不是有点重,维护性也不好,@Async这个注解就是为了解决这个问题,只需要在bean的方法上加上这和注解即可,就可以实现异步。

 

二、正文

先简单介绍下怎么使用

1、先在程序上加上@EnableAsync这个注解,可以指定执行器,如果不指定就从beanFactory中获取taskExecutor这个执行器

@Async(value = "executor")
    public void test(){

2、如果想自定义执行器,实现这个接口org.springframework.scheduling.annotation.AsyncConfigurer或者继承org.springframework.scheduling.annotation.AsyncConfigurerSupport这个类

public class AsyncExecutor implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
//        自定义线程池
        return Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    }

 

源码实现

@EnableAsync这个注解做什么了什么事情

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {

可以看到@Import引入了AsyncConfigurationSelector这个类,前面介绍spring ioc源码解析的时候这个@Import这个注解会把引入的类进行bean定义解析后注册到beanFactory而后进行实例化。

 

我们看到这个selector又继承了这个类

public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {

spring切面拦截到这个注解后进行下一步操作。

 

org.springframework.scheduling.annotation.AsyncConfigurationSelector#selectImports

184634_mNUf_3775437.gif

有两种通知模式实现。

 

我们可以看到@EnableAsync这个注解中是可以指定mode属性的,如果不指定默认设置是PROXY

AdviceMode mode() default AdviceMode.PROXY;

我们这里有以PROXY为例跟踪下。

 

会加载到这个类

org.springframework.scheduling.annotation.ProxyAsyncConfiguration

@Configuration
@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,BeanPostProcessor 前面spring ioc源码解析部分介绍过是对bean初始化过程的管理
      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);
      }
//    这里默认是jdk的动态代理,可以@EnableAsync这个注解的属性值,也可以指定
      bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
      bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
      return bpp;
   }

}

进入

org.springframework.scheduling.annotation.AbstractAsyncConfiguration

@Autowired(required = false)
   void setConfigurers(Collection<AsyncConfigurer> configurers) {
      if (CollectionUtils.isEmpty(configurers)) {
         return;
      }
      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();
   }

这个方法对线程进行赋值。

我们可以看到这个接口org.springframework.scheduling.annotation.AsyncConfigurer的唯一实现类org.springframework.scheduling.annotation.AsyncConfigurerSupport

public class AsyncConfigurerSupport implements AsyncConfigurer {

   @Override
   public Executor getAsyncExecutor() {
      return null;
   }

   @Override
   @Nullable
   public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
      return null;
   }

}

是一个空实现,多以想要自定义自己的线程池,实现这个接口org.springframework.scheduling.annotation.AsyncConfigurer或者继承org.springframework.scheduling.annotation.AsyncConfigurerSupport重写父类的方法。

 

异步方法返回值支持void、java.util.concurrent.Future、org.springframework.util.concurrent.ListenableFuture、java.util.concurrent.CompletableFuture

 

进入

org.springframework.aop.interceptor.AsyncExecutionInterceptor

找到

org.springframework.aop.interceptor.AsyncExecutionInterceptor#invoke这个方法,执行目标方法的切面方法

@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<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());
   }

进入

org.springframework.aop.interceptor.AsyncExecutionAspectSupport#determineAsyncExecutor

@Nullable
   protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
//    先从缓存中获取执行器
      AsyncTaskExecutor executor = this.executors.get(method);
      if (executor == null) {
         Executor targetExecutor;
//       从@Async注解中指定的属性值获取执行器
         String qualifier = getExecutorQualifier(method);
         if (StringUtils.hasLength(qualifier)) {
            targetExecutor = findQualifiedExecutor(this.beanFactory, qualifier);
         }
         else {
            targetExecutor = this.defaultExecutor;
            if (targetExecutor == null) {
               synchronized (this.executors) {
                  if (this.defaultExecutor == null) {
//                   从beanFactory中获取taskExecutor执行器
                     this.defaultExecutor = getDefaultExecutor(this.beanFactory);
                  }
                  targetExecutor = this.defaultExecutor;
               }
            }
         }
         if (targetExecutor == null) {
            return null;
         }
         executor = (targetExecutor instanceof AsyncListenableTaskExecutor ?
               (AsyncListenableTaskExecutor) targetExecutor : new TaskExecutorAdapter(targetExecutor));
//       放入缓存
         this.executors.put(method, executor);
      }
      return executor;
   }

如果@Async指定了执行器,就会使用这个执行器,如果没有指定就从beanFactory中获取taskExecutor这个执行器。

 

 

三、最后

本次源码解析到这里,仅供参考。

转载于:https://my.oschina.net/u/3775437/blog/1818866

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值