1.AsyncAnnotationBeanPostProcessor是主要逻辑类
(1)AsyncAnnotationBeanPostProcessor实现BeanFactoryAware接口
在setBeanFactory(BeanFactory beanFactory)中初始化advisor=AsyncAnnotationAdvisor()
(2)AsyncAnnotationBeanPostProcessor实现BeanPostProcessor接口
在postProcessorAfterInitialization(Object bean,String beanName)中判断是否生成代理对象,主要逻辑在AsyncAnnotationAdvisor中
2.AsyncAnnotationAdvisor的逻辑
(1)pointcut组合了AnnotationMatchingPointcut在类上及方法上的判断
类或者方法上有@Async,都有生成代理对象,在执行方法时会判断该方法上有没有@Aysnce,有才会调用拦截器上的advice
(2)advice=AnnotationAsyncExecutionInterceptor
advice才是真正执行的逻辑,它将任务提交到线程池中去执行
如果@Async指定value的值,则用beanName为value的线程池执行该方法
如果@Async没有指定value值,则去容器中找类型为TaskExecutor的线程池(如果找到多个或者没有找到,则用类型为Executor,beanName为taskExecutor去找),
如果还是没有找到,则用默认的SimpleAsyncTaskExecutor
3.@EnableAsync的理解
(1)参考@Configuration的理解import一个ImportSelector的现实类
(2) 通过AsyncConfigurationSelector加载proxyAsyncConfiguration
(3)通过proxyAsyncConfiguration加载AsyncAnnotationBeanPostProcessor
思考1:
(1)类A中的方法method1()调用method2()上的注释@Async能否生效
public void method1(){
this.method2();
}
@Async
public void method2(){
}
答:不能生效,this指的是当前对象,不是代理对象
2.能否使method1()调用method2()上的注释@Async生效?
可以改成下面
public void method1(){
((A)(AopContext.currentProxy())).method2();
}
@Async
public void method2(){
}
前提条件是使ProxyConfig.exposeProxy = true
思考2:
能否在一个方法上同时使用@Async跟@Scheduled注解
答:可以,ScheduledAnnotationBeanPostProcessor与AsyncAnnotationBeanPostProcessor的优先级一样(order一致),@Async生成的代理与@Scheduled创建的bean的调度任务执行先后顺序不确定。
如果先执行AsyncAnnotationBeanPostProcessor,则调度任务执行的是代理对象的方法(即调度线程池中再执行异步线程池,实际执行的是异步线程)。
如果先执行的是ScheduledAnnotationBeanPostProcessor,则调度任务执行的是原始对象的方法。
注:由于执行的是代理对象,CGLIB创建的代理对象实际上是目标对象的子类,不能重写private方法,所以方法不能是private,否则报下面的错误
Need to invoke method '%s' found on proxy for target class '%s' but cannot be delegated to target bean. Switch its visibility to package or protected
思考3:
现在两个类:类A中有 @Async方法,普通类B。类A与类B相互依赖,能否可行?
不可行,应用启动失败。
原因是:AsyncAnnotationBeanPostProcessor没有实现接口SmartInstantiationAwareBeanPostProcessor中的getEarlyBeanReference(Object bean,String beanName)的方法,使得循环依赖早期暴露的对象不是代理对象,与最终的生成的代理对象不一致。