好的,Shamseer,我有一点空闲时间,所以我尝试回答你的问题,而不需要你回答我在评论中提出的所有问题。我采用的方法是,我将不会使用参数名称,而是尝试匹配带有注释@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
请参见此答案,它回答了一个相关但比较简单的问题,其中包含类似的代码。
getArgs()
或反射代码。 - kriegaex@RequestParameter
中的“accessToken”,而不是通过变量名来识别,因为变量名很容易改变,似乎不太可靠。魔术参数名称是一个坏主意。 - kriegaex