AOP同方法调用失效?为什么我的AOP不生效? QAQ......这里是解决方案

自定义注解不生效的解决方法

Posted by Autuan.Yu on August 30, 2021

理解别人远比审判别人更为快乐。

问题描述

因业务功能需要,在service层中,有些方法使用了自定义注解。

最近,在Spring 中使用自定义注解时,发现了一个现象。

如果只有一个 service 层使用的话,是一点问题都没有的。比如说:

ControllerA#MethodA — 调用 —》 ServiceA#MethodA

但是如果在Service层中调用了两个拥有自定义注解的,就会有自定义注解失效。

例:

//  ==========   Controller Start ==========
/**
 * Controller 层
 * 省略类定义、自动注入等代码
 */
@RequestMapping("/example")
void example(){
    exampleService.example();
}
@RequestMapping("/depend")
void depend(){
    exampleService.depend();
}
//  ==========   Service End ==========


//  ==========   Service Start ==========
/**
 * Service 层
 * 实现类的方法,省略无关的代码块
 */
@MyAop
@Override
void example(){
    depend();
    // 一些其他操作
}

@MyAop
@Override
void depend(){
    // 一些业务处理
}

//  ==========   Service End ==========

在示例代码中,@MyAop是自定义的aop切面,可以实现业务上的功能。

如果在Controller 层 调用 depend 方法,MyAop 可以正常使用,但是如果在Controller 层调用example,则 depend() 执行时,@MyAop 不生效。

解决方案

不在同类中调用

将 depend 抽出,移动到其他类可以解决此问题 (推荐此方式)

//  ==========   Example Service Start ==========
@MyAop
@Override
void example(){
    dependService.depend();
    // 一些其他操作
}
//  ==========   Example Service Start ==========


//  ==========   Depend Service Start ==========
@MyAop
@Override
void depend(){
    // 一些业务处理
}
//  ==========   Depend Service Start ==========

基于容器

但也有可能说,depend() 方法就是要求在当前类中,和 example() 在同一类里。

这样的话,是不是就没有解决方案了呢?

当然不是,可以用这种方式解决:

((ExampleService) AopContext.currentProxy()).depend();

原因 1

Spring AOP 是基于代理的。

这里要了解的关键是,类方法中的客户端代码具有对代理的引用。也就是说,对该对象引用方法的调用就是对代理的调用。

所以,如果同函数中有其他方法调用,则意味着都将是针对 该引用而不是代理调用。

最终的结果则是: 自调用不会让和方法调用相关的aop执行。

PS

如果有任何问题或补充内容,欢迎在下方留言。

参考地址:

[1] Spring Core Technologies https://docs.spring.io/spring-framework/docs/5.3.10-SNAPSHOT/reference/html/core.html#aop-api