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

  • 相关阅读:
    Day12 尚硅谷JUC——集合的线程安全
    数据分析及治理工程师
    【C语言】指针和数组笔试题解析
    vue将base64编码转为pdf方法
    Java继承——抽象类与接口的比较以及内部类、匿名类、异常类......
    ios小程序蓝牙发送信息失败,报10004
    Asp.Net Core webapi+net6 使用资源筛选器(过滤器) 做缓存
    Google Chrome如何同步书签
    手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(七) - Elasticsearch 8.2 集成与配置
    【尚硅谷React】——React全家桶笔记
  • 原文地址:https://blog.csdn.net/hujiakuan19910201/article/details/133941437