Java设计模式之代理模式与@Async异步注解失效的解决
自定义注解实现方式
JDK动态代理实现自定义异步注解(@Async)
实现思路:
- 首先自定义一个注解,命名为:
ExtAsync
- 实现一个接口,这个接口的实现类就是被代理类
- 实现jdk的
InvocationHandler
接口,根据反射获取目标方法的信息,判断是否有异步注解,如果有则另起一个线程异步执行去。
1、异步注解
2、接口和实现类
3、JDK动态代理需要实现的InvocationHandler
接口类
4、测试类
总结分析:加上自定义的异步注解,查看输出的日志顺序,然后注释掉异步注解,再看输出的日志顺序。
SpringAOP实现自定义异步注解
核心在于AOP切面类上:拦截加了自定义异步注解的方法,看起一个线程执行目标方法。
Spring的异步注解@Async失效分析
注解原理:AOP技术–》动态代理技术
Spring中是如何综合使用Cglib和Jdk动态代理呢?
- 如果被代理类有实现接口的情况下默认采用 Jdk动态代理 可以转换为Cglib
- 如果被代理类没有实现接口的情况下采用Cglib
异步注解失效:
1、如果控制类(加了@RestController的类)中的有方法加上了异步注解,并且有实现接口的情况下,则采用JDK动态代理,控制类没有注册到SpringMVC容器中。
2、如果控制类(加了@RestController的类)中有的方法加上了异步注解,但是没有实现接口的情况下,则采用CGLIB动态代理,控制类可以注册到SpringMVC容器,但是异步注解会失效。
为什么失效?
底层使用动态代理模式,在代理类创建线程,如果没有经过代理类就不会创建线程,所以必须从Sping中获取代理对象,通过代理对象.方法,才会经过代理类实现创建线程异步操作。因为在控制类的方法增加异步注解的时候,调用该方法时调用的不是代理对象的方法,而是当前对象的方法。
1、不要在当前类直接使用异步注解,因为没有经历过代理类。
2、官方建议新建一个类来进行异步操作。
原理: 如果在控制类(实现接口的类)上的方法上加了异步注解,采用JDK动态代理技术,代理基于接口实现,而接口中没有加上@RestController
注解,所以代理对象无法注册到SpringMVC容器中。反之,如果控制类没有实现接口,则采用CGLIB动态代理,生成的代理对象是采用继承目标对象(@RestController
也会继承过来),这时代理对象可以注入带SpringMVC容器中。
到此这篇关于Java设计模式之代理模式与@Async异步注解失效的解决的文章就介绍到这了,更多相关Java代理模式内容请搜索编程学习网以前的文章希望大家以后多多支持编程学习网!