一、问题起源
我们定义了一个注解如下:
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