springboot中@Async的使用

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)的方法,使得循环依赖早期暴露的对象不是代理对象,与最终的生成的代理对象不一致。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值