Spring 源码学习 - @Async注解实现原理

> 本文作者:geek,一个聪明好学的朋友

##  1. 简介
开发中我们需要异步执行某个耗时任务时候需要@Async,以下我将从源码角度解释该注解的实现原理。

## 2.前提条件@EnableAsync

​      项目使用中,需要添加@EnableAsync注解支持,才能使用@Async(也支持自定义注解)生效。@EnableAsync(默认mode为AdviceMode.PROXY情况下)作用为了给spring项目加入AsyncConfigurationSelector,从而引入AsyncAnnotationBeanPostProcessor。

```java
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {}
```

```java
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");
        /**
         *  创建postProcessor,支持定制executor与exceptionHandler
         */
    AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
        bpp.configure(this.executor, this.exceptionHandler);
        Class 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.getNumber("order"));
        return bpp;
    }

}
```

## 3.AsyncAnnotationBeanPostProcessor的作用

     AsyncAnnotationBeanPostProcessor为加了@Async注解的方法的目标类加入AsyncAnnotationAdvisor。AsyncAnnotationAdvisor也即是spring AOP中责任链调用的advisor,可见被@Async的实现是通过生成代理对象来实现的。

```java
public class AsyncAnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor {

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        super.setBeanFactory(beanFactory);

        AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
        if (this.asyncAnnotationType != null) {
            advisor.setAsyncAnnotationType(this.asyncAnnotationType);
        }
        advisor.setBeanFactory(beanFactory);
        this.advisor = advisor;
    }

}
```

```java
public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {
public AsyncAnnotationAdvisor(
            @Nullable Supplier executor, @Nullable Supplier exceptionHandler) {

  /**
  *  支持Async与Asynchronous
  */
        Set> asyncAnnotationTypes = new LinkedHashSet<>(2);
        asyncAnnotationTypes.add(Async.class);
        try {
            asyncAnnotationTypes.add((Class)
                    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);
    }
  
  /**
     * // 这个最终又是委托给`AnnotationAsyncExecutionInterceptor`,它是一个具体的增强器,有着核心内容
     * @param executor
     * @param exceptionHandler
     * @return
     */
    protected Advice buildAdvice(
            @Nullable Supplier executor, @Nullable Supplier exceptionHandler) {

        AnnotationAsyncExecutionInterceptor interceptor = new AnnotationAsyncExecutionInterceptor(null);
        interceptor.configure(executor, exceptionHandler);
        return interceptor;
    }
 }
```

## 4.AnnotationAsyncExecutionInterceptor核心内容

​    AnnotationAsyncExecutionInterceptor继承AsyncExecutionInterceptor间接实现了MethodInterceptor,该拦截器的实现的invoke方法把原来方法的调用提交到新的线程池执行,从而实现了方法的异步。当需要获得异步结果时,支持CompletableFuture,ListenableFuture,Future的返回。

```java
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");
        }
    /**
    *  构建放到AsyncTaskExecutor执行Callable Task
    */
        Callable 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());
    }
}
```

## 5. 使用注意事项

5.1使用@Aysnc的时候最好配置一个线程池Executor以让线程复用节省资源,或者为SimpleAsyncTaskExecutor设置基于线程池实现的ThreadFactory,在否则会默认使用SimpleAsyncTaskExecutor,该executor会在每次调用时新建一个线程。

```java
/**
* SimpleAsyncTaskExecutor继承自CustomizableThreadCreator,可以看到线程直接new
*/
public class CustomizableThreadCreator implements Serializable {    
public Thread createThread(Runnable runnable) {
        Thread thread = new Thread(getThreadGroup(), runnable, nextThreadName());
        thread.setPriority(getThreadPriority());
        thread.setDaemon(isDaemon());
        return thread;
    }
}
```

5.2关于方法内部调用,@Async注解会失效

```java
public class QueryServiceImpl implements QueryService {
    @Override
    public void A() {
        System.out.println("QueryServiceImpl.A");
        B();
    }

    @Async
    @Override
    public void B() {
        System.out.println("QueryServiceImpl.B");
    }
}

```

​       失效原因:A方法中调用B方法,调用即为this.B(),this对象为原始的对象,并不是增强后代理对象,当然不能生效了。建议重构分开调用,如果硬是需要内部调用则是只能通过获取代理对象来实现。

```java
@Component("q")
public class QueryServiceImpl implements QueryService {

    @Autowired
    private ApplicationContext applicationContext;


    @Override
    public void A() {
        System.out.println("QueryServiceImpl.A");
        QueryService queryService = (QueryService)applicationContext.getBean("q");
        queryService.B();
    }

    @Async
    @Override
    public void B() {
        System.out.println("QueryServiceImpl.B");
    }
}

```
参考

- [【小家Spring】Spring异步处理@Async的使用以及原理、源码分析(@EnableAsync)]([https://blog.csdn.net/f641385712/article/details/89430276]))
  


查看更多文章关注公众号:**好奇心森林** 
![Wechat](https://fintech-images.oss-cn-shenzhen.aliyuncs.com/1.jpg)
 

 

你可能感兴趣的:(技术总结)