解决AOP嵌套失效的问题
一、问题起源
我们定义了一个注解如下:
1 /**
2 * AOP的切面嵌套测试-注解
3 *
4 * @author suxiaolong
5 */
6 @Target({ElementType.PARAMETER, ElementType.METHOD})
7 @Retention(RetentionPolicy.RUNTIME)
8 public @interface AnnotationNest {
9
10 /**
11 * 模块名称
12 *
13 * @return 模块名称
14 */
15 String moduleName();
16
17 }
我们这样使用它——将注解加到同一个类的多个方法中,这多个方法中存在相到调用:
1 @Component
2 public class AnnotationNestClass {
3 @AnnotationNest(moduleName = "parent")
4 public void parent(String string) throws Exception {
5 System.out.println("parent-body");
6 this.child(string);
7 }
8
9 @AnnotationNest(moduleName = "child")
10 public void child(String string) {
11 System.out.println("child-body");
12 }
13 }
调用:
1 @RestController
2 @RequestMapping(value = "/user")
3 public class SignController {
4 @Autowired
5 AnnotationNestClass annotationNestClass;
6
7 @GetMapping(value = "/query")
8 public void queryUser() throws Exception{
9 annotationNestClass.parent("parent");
10 }
11 }
如果是上面的这种调用,那么AnnotationNestClass.child()的切面将不能进入。
二、原因
在AnnotationNestClass中用this调用的时候,this代表的不再是代理类,而是当前这个类本身,因而切面无法进入。
三、解决办法一:自我注入
通过自我注入,这里就能拿到代理类。
四、解决方法二:通过AopContext.curretnProxy()
这里要注意,AopContxt.currentProxy()方法不能放到多线程中进行获取,因为AopContext.currentProxy()使用的是LocalThread存储当前代理,在新的线程中,LocalThread为空,所以就拿不到代理。
如果想要在多线程环境中获取当前类的代码,就在线程外获取,传递给线程去处理,如下所示:
五、解决方法三:引入一个新的类
将方法child()放到一个新的类,这种方法就不推荐了。
六、参考文章
1、 https://blog.csdn.net/hl_java/article/details/79445799
2、 https://blog.csdn.net/tjreal/article/details/80714294
3、 https://blog.csdn.net/Liu_York/article/details/86681933
4、 https://www.cnblogs.com/yjmyzz/p/how-to-use-aop-in-multi-thread-spring-application.html