解决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

 

posted @ 2020-05-02 16:21  gudi  阅读(1814)  评论(0编辑  收藏  举报