泛型擦除的实用案例: 事务失效改成手动获取当前代理类进行

前言

       第一次写博客,工作这么久,偶尔会遇到一些问题,就想记录下来,如有不对,可以及时联系我修改,谢谢!

 

问题:

      在一次工作中,需要用的异步场景,因为项目代码是用springBoot, 所以我们都知道用@Async 注解可以解决,但是这个注解和@Transaction一样

是可能会失效的(具体原因需要了解spring与动态代理)。

 

异步方法代码:

   @Async
    public void async() throws InterruptedException {
        //当前线程===第一次:async=======http-nio-8081-exec-1
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        System.out.println(stackTrace[1].getMethodName()+"======="+Thread.currentThread().getName());
        Thread.sleep(5000);
        System.out.println("B-Async end");

    }

 

调用处:

  @Override
    public void test() throws InterruptedException {
        //不生效 原因: 直接调用相当于 this.async(),而this是当前类,是没有经过 spring的Aop增强的,所以这里必须是代理对象调用才能生效。
        async();
        //生效  原因: 获取的是当前对象的代理对象,代理对象是被增强过的。
        ((AsyncInterfaceImpl) AopContext.currentProxy()).async();
//        System.out.println("test end");
    }

 

很明显直接  async();是不生效的,因为当前类不是代理类,

  用 ((AsyncInterfaceImpl) AopContext.currentProxy()).async(); 就可以解决, 但是这样写每次都要强转非常麻烦,所以我们决定写一个工具类。

 

解决

工具类代码:

 

public class AopUtils {

    public static <T> T  getClassT(Class<T> c){

        return   c.cast(AopContext.currentProxy());

    }
    
}

 

采用工具类后:

    @Override
    @GetMethod
    public void test() throws InterruptedException {
        //不生效
        async();
       
    
//工具类生效
     AsyncInterfaceImpl service = AopUtils.getClassT(this.getClass());
service.async();
// ((AsyncInterfaceImpl) AopContext.currentProxy()).async(); // System.out.println("test end"); }

很明显看到,我们利用泛型,以后再也不用类型转换了,能够直接调用方法。

 

感谢观看,希望以后有时间自己也能多写点,以免每次工作用完就忘了 ~

 

posted @ 2021-05-15 09:13  Rick_Leee  阅读(86)  评论(0)    收藏  举报