反射获取方法注解直接调用Method.getAnnotation()或getDeclaredAnnotations(),而参数注解需通过getParameterAnnotations()获取二维数组,按索引遍历各参数的注解;Java 8+中Parameter.getAnnotation()依赖-parameters编译选项,但getParameterAnnotations()始终可用且更稳定。

反射获取方法注解和参数注解的API路径不同,核心差异在于:方法注解直接挂在 Method 对象上,而参数注解必须通过 Method 获取参数类型信息后,再从每个参数索引提取,且需注意 Java 8+ 的 @Parameter 和 @Parameterized 行为区别。
获取方法上的注解(如 @RequestMapping、@Transactional)
直接调用 Method.getAnnotation(Class<T>) 或 Method.getAnnotations() 即可,因为方法本身就是一个完整的反射元素,其上的注解属于该元素的元数据。
-
method.getAnnotation(ResponseBody.class)—— 返回单个注解实例 -
method.getDeclaredAnnotations()—— 返回所有声明的注解(含重复注解容器) - 若注解带
@Retention(RetentionPolicy.RUNTIME),运行时可见;否则反射不可见
获取方法参数上的注解(如 @PathVariable、@RequestParam)
参数注解不绑定在独立对象上,而是依附于“参数位置”,必须通过 Method.getParameterAnnotations() 获取二维数组:Annotation[][],其中外层数组对应参数顺序,内层数组是该参数上的全部注解。
Annotation[][] paramAnns = method.getParameterAnnotations();-
paramAnns[i]表示第i个参数的所有注解(Annotation[]) - 需遍历
paramAnns[i]才能查到具体注解,例如:Arrays.stream(paramAnns[i]).filter(a -> a instanceof RequestParam).findFirst() - 注意:Java 8 引入
Method.getParameters()返回Parameter[],但Parameter.getAnnotation()默认不可见——除非编译时加-parameters参数且注解声明了@Retention(RUNTIME)
关键限制与常见陷阱
参数名在字节码中默认不保留,导致仅靠反射无法可靠获取形参名称(如 name="userId"),Spring 等框架依赖 -parameters 编译选项或 @Param 显式指定;而方法级注解无此限制。
- 未加
-parameters时,method.getParameters()[i].getName()返回arg0、arg1等占位符 -
getParameterAnnotations()始终可用,不依赖编译选项,是获取参数注解最稳定的方式 - 泛型参数上的注解(如
@RequestBody List<@Valid User>)需用Method.getGenericParameterTypes()配合AnnotatedType(Java 8+)才能读取
推荐实践方式
统一使用 Method.getParameterAnnotations() 处理参数注解,避免依赖 Parameter 对象;方法注解保持直取。框架层(如 Spring MVC)内部正是这样区分处理的。
- 检查注解存在性优先用
isAnnotationPresent(...),比捕获 null 更安全 - 批量扫描时缓存
Method反射结果,避免重复解析 - 自定义注解务必声明
@Retention(RetentionPolicy.RUNTIME),否则反射读不到

















