Spring Boot项目使用Aspect捕获带自定义注解的参数失败如何解决
问题根因
Java 中所有运行时注解的实例本质上都是 JDK 动态代理生成的接口实现类对象,你直接调用annotation.getClass().getName()获取到的是动态代理类的类名(也就是你看到的com.sun.proxy.$ProxyXXX),并非原注解接口的全限定名,所以匹配逻辑永远不成立。
解决方案
有三种常用的修复方式,推荐优先使用第一种,写法最简洁不易出错:
方案1:直接使用Parameter.isAnnotationPresent内置方法判断
不用自己遍历注解,直接调用Parameter的原生方法判断是否标注了目标注解,修改getAnnotatedParameter方法即可:
public Object getAnnotatedParameter(JoinPoint joinPoint, Class<? extends Annotation> annotatedClazz) { MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); Parameter[] params = methodSignature.getMethod().getParameters(); for (int i = 0; i < params.length; i++) { if (params[i].isAnnotationPresent(annotatedClazz)) { // 如果你需要返回参数的实际值,就返回joinPoint.getArgs()[i] // 如果你需要返回Parameter元信息,就返回params[i] return joinPoint.getArgs()[i]; } } return null; }
对应调用处直接传入DTO.class即可,不需要额外修改其他逻辑。
方案2:修改注解类名匹配逻辑
如果你需要保留自定义遍历注解的逻辑,不要用注解实例的类名匹配,改用annotation.annotationType()获取原注解接口类型再匹配:
private boolean isParamAnnotatedWith(Parameter param, String annotationClassName) { for (Annotation annotation : param.getAnnotations()) { // annotationType()返回的是注解对应的原始接口类型 if (annotation.annotationType().getName().equals(annotationClassName)) { return true; } } return false; }
方案3:用isInstance直接判断类型
不需要匹配类名,直接通过Class的实例判断逻辑校验:
private boolean isParamAnnotatedWith(Parameter param, Class<? extends Annotation> annotatedClazz) { for (Annotation annotation : param.getAnnotations()) { if (annotatedClazz.isInstance(annotation)) { return true; } } return false; }
额外注意点
你当前代码里还存在两个容易引发问题的写法:
@Before通知的方法不能使用ProceedingJoinPoint,也不需要返回值,ProceedingJoinPoint是环绕通知@Around专用的参数,如果是前置通知请改用JoinPoint,返回值改为void- 你原来的
getAnnotatedParameter返回的是Parameter参数元信息,不是方法执行时的实际参数值,如果需要拿实际传参要从joinPoint.getArgs()数组中取下标对应的对象
内容的提问来源于stack exchange,提问作者Joy
相关产品推荐
相关产品推荐

