好的,Shamseer,我只是有一点空闲时间,所以我试图在你不回答我的 cmets 的所有问题的情况下回答你的问题。我这样做的方法是我将不使用参数名称,但尝试使用注释@RequestParam("accessToken") 匹配参数,即我将匹配注释类型和具有“accessToken”魔术名称而不是方法参数名称的值,由于在编译期间从类文件中剥离调试信息或由于混淆,可能会由于不了解您方面的人的简单重构而改变。
这是一些自洽的示例代码,它针对 AspectJ 而不是 Spring AOP 进行了测试,但后者的语法无论如何都是前者语法的子集:
带有 main 方法的示例类:
共有三种方法,所有方法都在其中一个参数上有@RequestParam注解,但其中只有两个具有“accessToken”的神奇值。无论参数类型如何(一个String 和一个int)都应该匹配,但不应匹配带有@RequestParam("someParameter") 的那个。严格来说,所有的方法执行都是匹配的,但是运行时反射会消除不想要的。如果您的注释将在类或方法级别或参数类型上,我们可以直接在切入点中匹配它们而无需反射,但在参数注释的情况下,这超出了 AspectJ 当前 (v1.8.4) 的能力,我们必须使用反射,很遗憾。
package de.scrum_master.app;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
public class MyResponse {
public MyResponse saveUser(
@RequestParam("accessToken") String accessToken,
@RequestBody final UserDto userDto
) {
return this;
}
public MyResponse doSomething(
@RequestParam("someParameter") String text,
@RequestBody final UserDto userDto
) {
return this;
}
public MyResponse doSomethingElse(
@RequestParam("accessToken") int number
) {
return this;
}
public static void main(String[] args) {
MyResponse myResponse = new MyResponse();
myResponse.doSomething("I am not a token", new UserDto());
myResponse.saveUser("I am a token", new UserDto());
myResponse.doSomethingElse(12345);
}
}
用于编译代码的虚拟助手类:
package de.scrum_master.app;
public class UserDto {}
方面:
请注意,我的包罗万象的切入点execution(* *(..)) 仅用于说明。你应该把范围缩小到你真正想要匹配的方法。
package de.scrum_master.aspect;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.bind.annotation.RequestParam;
@Aspect
public class AccessTokenAspect {
@Around("execution(* *(..))")
public Object handleAccessToken(ProceedingJoinPoint thisJoinPoint) throws Throwable {
System.out.println(thisJoinPoint);
Object[] args = thisJoinPoint.getArgs();
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getStaticPart().getSignature();
Method method = methodSignature.getMethod();
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
assert args.length == parameterAnnotations.length;
for (int argIndex = 0; argIndex < args.length; argIndex++) {
for (Annotation annotation : parameterAnnotations[argIndex]) {
if (!(annotation instanceof RequestParam))
continue;
RequestParam requestParam = (RequestParam) annotation;
if (! "accessToken".equals(requestParam.value()))
continue;
System.out.println(" " + requestParam.value() + " = " + args[argIndex]);
}
}
return thisJoinPoint.proceed();
}
}
控制台输出:
execution(void de.scrum_master.app.MyResponse.main(String[]))
execution(MyResponse de.scrum_master.app.MyResponse.doSomething(String, UserDto))
execution(MyResponse de.scrum_master.app.MyResponse.saveUser(String, UserDto))
accessToken = I am a token
execution(MyResponse de.scrum_master.app.MyResponse.doSomethingElse(int))
accessToken = 12345
另请参阅this answer,了解一个相关但更简单的问题,使用类似的代码。