spring异步调用注解@Async实现原理分析

1、首先看下注解,可以加在类上,也可以加在方法上

spring async线程池卡死原因 spring async原理_aop

2、需要在启动类加上@EnableAsync注解

spring async线程池卡死原因 spring async原理_父类_02


spring async线程池卡死原因 spring async原理_父类_03

  • 导入了AsyncConfigurationSelector

调用selectImports方法。默认会注入ProxyAsyncConfiguraion

spring async线程池卡死原因 spring async原理_spring async线程池卡死原因_04

  • 看下ProxyAsyncConfiguration类

spring async线程池卡死原因 spring async原理_spring async线程池卡死原因_05

会创建一个后置处理器AsyncAnnotationBeanPostProcessor,看下这个后置处理器

  • AsyncAnnotationBeanPostProcessor

    继承关系如下
    AsyncAnnotationBeanPostProcessor----》AbstractBeanFactoryAwareAdvisingPostProcessor----》AbstractAdvisingBeanPostProcessor implements BeanFactoryAware

由于实现了BeanFactoryAware,spring创建对象后会调用setBeanFactory方法,下图为spring创建对象逻辑,可忽略

spring async线程池卡死原因 spring async原理_父类_06

  • AsyncAnnotationBeanPostProcessor的setBeanFactory方法
  • 进入AsyncAnnotationAdvisor构造方法

    主要是红框中构造了切面和切入点,

    切面是一个AnnotationAsyncExecutionInterceptor拦截器

关注构造切入点

spring async线程池卡死原因 spring async原理_spring async线程池卡死原因_07


创建了一个类切入点,和一个方法切入点

类切入点:

spring async线程池卡死原因 spring async原理_拦截器_08

方法切入点:

spring async线程池卡死原因 spring async原理_拦截器_09


spring async线程池卡死原因 spring async原理_spring async线程池卡死原因_10


小结:创建方法匹配器时会默认创建一个ClassFilter.TRUE的类的过滤器,这个在之前工具类中有说过(AopUtis工具类),就是不对类进行过滤

3、AsyncAnnotationBeanPostProcessor后置处理器的作用时机

在spring创建单实例对象完成时会进行postProcessAfterInitialization调用

AsyncAnnotationBeanPostProcessor的父类AbstractAdvisingBeanPostProcessor中有这个方法

public Object postProcessAfterInitialization(Object bean, String beanName) {
 			...
			//001
            if (this.isEligible(bean, beanName)) {
                ProxyFactory proxyFactory = this.prepareProxyFactory(bean, beanName);
                if (!proxyFactory.isProxyTargetClass()) {
                    this.evaluateProxyInterfaces(bean.getClass(), proxyFactory);
                }

                proxyFactory.addAdvisor(this.advisor);
                this.customizeProxyFactory(proxyFactory);
                return proxyFactory.getProxy(this.getProxyClassLoader());
            } else {
                return bean;
            }
        }
    }
  • isEligible判断当前创建的对象是否满足条件
    我们关注下这个类的创建

    创建后进入后置处理器操作,进入上面代码001位置

使用工具类进行判断是否符合

spring async线程池卡死原因 spring async原理_aop_11


这个advisor我们上面也看到过,是个AsyncAnnotationAdvisor

spring async线程池卡死原因 spring async原理_父类_12

其中的属性advice是我们之前看到的切面AnnotationAsyncExecutionInterceptor

最终符合条件返回true,进入代码001位置

spring async线程池卡死原因 spring async原理_spring async线程池卡死原因_13

  • 创建代理工厂,返回代理对象

proxyFactory添加了AsyncAnnotationAdvisor对象

spring async线程池卡死原因 spring async原理_拦截器_14


spring async线程池卡死原因 spring async原理_spring async线程池卡死原因_15

调用父类ProxyCreatorSupport的createAopProxy方法

spring async线程池卡死原因 spring async原理_aop_16


spring async线程池卡死原因 spring async原理_spring_17


spring async线程池卡死原因 spring async原理_spring_18

获取aop代理工厂,创建aop代理时将this本身作为参数传入,this就说proxyFactory

最终proxyFactory会赋值给CglibAopProxy的advised属性

spring async线程池卡死原因 spring async原理_aop_19


最后调用CglibAopProxy的getProxy方法

spring async线程池卡死原因 spring async原理_spring_20

下图接上面getProxy方法

spring async线程池卡死原因 spring async原理_aop_21


spring async线程池卡死原因 spring async原理_aop_22

spring async线程池卡死原因 spring async原理_spring_23

4、代理对象接收请求调用

进入intercept方法

spring async线程池卡死原因 spring async原理_spring async线程池卡死原因_24

获取拦截器链

图1

spring async线程池卡死原因 spring async原理_spring_25

getInterceptorsAndDynamicInterceptionAdvice这个方法会获取ProxyFactory里面的advised

spring async线程池卡死原因 spring async原理_拦截器_26

获取到了之前定义在AsyncAnnotationAdvisor对象里面的AnnotationAsyncExecutionInterceptor拦截器

spring async线程池卡死原因 spring async原理_aop_27

接图1继续执行

spring async线程池卡死原因 spring async原理_spring async线程池卡死原因_28

进入AnnotationAsyncExecutionInterceptor父类的invoke

spring async线程池卡死原因 spring async原理_spring async线程池卡死原因_29


spring async线程池卡死原因 spring async原理_spring async线程池卡死原因_30


使用线程池提交任务,达到异步执行效果