因为@controller是类级别注解,getmethodannotation只查找方法级注解,故返回null;应通过getbeantype()获取控制器类再调用getannotation()或annotationutils.findannotation()。

在 Spring MVC 中,HandlerMethod 本身**不能直接通过 getMethodAnnotation 读取 @Controller 注解**,因为 @Controller 是标注在**类(Class)上**的,不是标注在 HandlerMethod 对应的处理方法(Method)上的。所以调用 handlerMethod.getMethodAnnotation(Controller.class) 总是返回 null。
为什么 getMethodAnnotation 拿不到 @Controller?
getMethodAnnotation(Class<t> annotationClass)</t> 只查找当前 handler 方法(即 @RequestMapping 或其派生注解标记的方法)上声明的注解,例如:
@GetMapping@ResponseBody- 自定义方法级注解(如
@NeedAuth)
而 @Controller(或 @RestController)是作用于整个类的,属于类级别注解,必须从 handler 方法所属的类(即 Controller 类)上获取。
正确获取 @Controller 注解的方式
你应该通过 HandlerMethod.getBeanType() 或 HandlerMethod.getMethod().getDeclaringClass() 获取控制器类,再调用 getAnnotation():
HandlerMethod handlerMethod = ...;
Class> controllerClass = handlerMethod.getBeanType(); // 推荐:更准确(考虑代理场景)
// 或 Class> controllerClass = handlerMethod.getMethod().getDeclaringClass();
Controller controllerAnno = controllerClass.getAnnotation(Controller.class);
RestController restControllerAnno = controllerClass.getAnnotation(RestController.class);
if (controllerAnno != null || restControllerAnno != null) {
// 确实是 Controller 类
}
实际使用建议(比如在拦截器或 ArgumentResolver 中)
如果你需要判断某个请求是否由 Controller 处理,或需读取 Controller 类上的元信息(如自定义类注解),请按以下方式操作:
- 优先用
handlerMethod.getBeanType()—— 它能正确处理 CGLIB 代理(如@Transactional增强后的 Controller) - 避免用
handlerMethod.getMethod().getDeclaringClass()在有代理时可能拿到的是代理类(非原始 Controller 类) - 若需同时支持
@Controller和@RestController,可统一检查是否为 Spring MVC 控制器类型:AnnotationUtils.findAnnotation(controllerClass, Controller.class) != null ||<br> AnnotationUtils.findAnnotation(controllerClass, RestController.class) != null
扩展:读取 Controller 类上的自定义注解
比如你定义了 @ApiVersion("v2") 标在 Controller 类上:
@ApiVersion("v2")
@Controller
public class UserController { ... }
那么在 HandlerMethod 处可这样读取:
Class> controllerClass = handlerMethod.getBeanType();
ApiVersion apiVer = AnnotationUtils.findAnnotation(controllerClass, ApiVersion.class);
if (apiVer != null) {
String version = apiVer.value(); // "v2"
}
注意:推荐使用 AnnotationUtils.findAnnotation 而非原生 getAnnotation,它支持 Spring 的元注解(如 @RestController 包含 @Controller)和桥接注解,更健壮。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











