代理对象不继承实现类,仅实现接口,故getclass().getannotation()只能获取接口注解;需通过原始实现类class对象读取类及方法注解,参数注解须用getparameterannotations()并确保运行时保留。

动态代理对象本身不继承实现类,只实现接口,所以直接对代理对象调用 getClass().getAnnotation() 只能拿到接口上的注解,拿不到实现类的注解——这是常见误区的根源。
为什么代理类读不到实现类的注解
Java 的 Proxy.newProxyInstance 创建的是一个**全新生成的、仅实现指定接口的匿名类**。它和你的实现类(比如 OrderServiceImpl)没有继承或组合关系,JVM 也不会自动把实现类上的注解“复制”过去。因此:
-
proxy.getClass().getAnnotation(MyAspect.class)→ 返回null(除非你在接口上也声明了该注解) -
proxy.getClass().getDeclaredMethods()→ 返回的是代理类自己的桥接方法,不是原始实现方法 - 注解信息在字节码层面只保留在原始类/方法定义处,代理类中不携带
核心解决思路:绕过代理对象,直连原始类型
关键在于——你一定知道被代理的是哪个类。只要在创建代理时把实现类的 Class 对象传进去,后续所有注解读取都基于它,而不是代理对象的 getClass():
- 在
InvocationHandler的invoke方法中,用传入的targetClass获取目标方法:targetClass.getMethod(method.getName(), method.getParameterTypes()) - 再对该
Method调用getAnnotation()或isAnnotationPresent() - 类级注解同理:
targetClass.getAnnotation(MyConfig.class)
读取方法参数注解的特别注意点
如果要读取方法参数上的注解(如 @RequestParam、@ApiParam),不能依赖 method.getParameters()[i].getAnnotation(),因为:
- JVM 默认不保留参数名和参数注解元数据
- 必须使用
method.getParameterAnnotations()—— 它返回Annotation[][],外层数组长度等于参数个数 - 对第
i个参数,遍历annotations[i]数组,用instanceof或annotation.annotationType() == RequestParam.class判定 - 确保自定义参数注解声明了
@Target(ElementType.PARAMETER)和@Retention(RetentionPolicy.RUNTIME)
结合 Spring 等框架的实用建议
在真实项目中,尤其涉及 Spring MVC 参数绑定逻辑时:
- 不要仅靠
@ApiParam.value()推断参数位置,优先识别@PathVariable、@RequestParam、@RequestBody这些原生注解类型 - 若同时存在
@RequestParam("uid")和@ApiParam(name="id"),以 Spring 注解为准,@ApiParam仅补充描述 - 对于 Lombok
@Builder或字节码增强工具,确认它们未擦除-parameters编译信息,否则getParameterAnnotations()可能为空











