spring异步调用注解@Async实现原理分析
1、首先看下注解,可以加在类上,也可以加在方法上
2、需要在启动类加上@EnableAsync注解
- 导入了AsyncConfigurationSelector
调用selectImports方法。默认会注入ProxyAsyncConfiguraion
- 看下ProxyAsyncConfiguration类
会创建一个后置处理器AsyncAnnotationBeanPostProcessor,看下这个后置处理器
- AsyncAnnotationBeanPostProcessor
继承关系如下
AsyncAnnotationBeanPostProcessor----》AbstractBeanFactoryAwareAdvisingPostProcessor----》AbstractAdvisingBeanPostProcessor implements BeanFactoryAware
由于实现了BeanFactoryAware,spring创建对象后会调用setBeanFactory方法,下图为spring创建对象逻辑,可忽略
- AsyncAnnotationBeanPostProcessor的setBeanFactory方法
- 进入AsyncAnnotationAdvisor构造方法
主要是红框中构造了切面和切入点,
切面是一个AnnotationAsyncExecutionInterceptor拦截器
关注构造切入点
创建了一个类切入点,和一个方法切入点
类切入点:
方法切入点:
小结:创建方法匹配器时会默认创建一个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位置
使用工具类进行判断是否符合
这个advisor我们上面也看到过,是个AsyncAnnotationAdvisor
其中的属性advice是我们之前看到的切面AnnotationAsyncExecutionInterceptor
最终符合条件返回true,进入代码001位置
- 创建代理工厂,返回代理对象
proxyFactory添加了AsyncAnnotationAdvisor对象
调用父类ProxyCreatorSupport的createAopProxy方法
获取aop代理工厂,创建aop代理时将this本身作为参数传入,this就说proxyFactory
最终proxyFactory会赋值给CglibAopProxy的advised属性
最后调用CglibAopProxy的getProxy方法
下图接上面getProxy方法
4、代理对象接收请求调用
进入intercept方法
获取拦截器链
图1
getInterceptorsAndDynamicInterceptionAdvice这个方法会获取ProxyFactory里面的advised
获取到了之前定义在AsyncAnnotationAdvisor对象里面的AnnotationAsyncExecutionInterceptor拦截器
接图1继续执行
进入AnnotationAsyncExecutionInterceptor父类的invoke
使用线程池提交任务,达到异步执行效果