深入理解 Spring 的 MethodParameter 类

MethodParameter 是 Spring 框架中一个非常重要的类,它封装了方法参数(或返回类型)的元数据信息。这个类在 Spring MVC、AOP、数据绑定等多个模块中都有广泛应用。

核心功能

MethodParameter 主要提供以下功能:

  1. 获取参数类型信息 - 包括泛型类型信息

  2. 获取参数注解 - 包括参数上的注解

  3. 获取参数名称 - 如果编译时保留了参数名信息

  4. 获取所属方法或构造器 - 参数所属的方法或构造器信息

主要应用场景

1. Spring MVC 参数解析

在控制器方法参数解析时,Spring 使用 MethodParameter 来确定如何解析请求参数:

public class MyArgumentResolver implements HandlerMethodArgumentResolver {@Overridepublic boolean supportsParameter(MethodParameter parameter) {// 判断是否支持该参数类型return parameter.getParameterType().equals(MySpecialType.class);}@Overridepublic Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {// 实际解析逻辑}
}

2. 响应体处理 (ResponseBodyAdvice)

如前面讨论的 ResponseBodyAdvice 中使用 MethodParameter 判断返回类型:

@Override
public boolean supports(MethodParameter returnType, Class<?> converterType) {// 根据返回类型决定是否应用 advicereturn returnType.getMethod().getReturnType() != Void.TYPE;
}

3. 数据绑定和验证

Spring 使用 MethodParameter 进行数据绑定和验证:

public void bindAndValidate(MethodParameter parameter, Object target, Errors errors) {// 获取参数上的验证注解Annotation[] annotations = parameter.getParameterAnnotations();// 执行绑定和验证逻辑
}

关键 API 详解

1. 获取类型信息

// 获取参数类型(包括泛型信息)
Class<?> parameterType = parameter.getParameterType();// 获取嵌套泛型类型
ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter);
Class<?> genericType = resolvableType.getGeneric(0).resolve();

2. 获取注解

// 获取参数上的特定注解
RequestParam requestParam = parameter.getParameterAnnotation(RequestParam.class);// 获取所有注解
Annotation[] annotations = parameter.getParameterAnnotations();

3. 获取参数名

// 获取参数名(需要编译时保留参数名信息)
String paramName = parameter.getParameterName();

4. 获取方法/构造器信息

// 获取所属方法
Method method = parameter.getMethod();// 获取所属构造器
Constructor<?> constructor = parameter.getConstructor();

实际应用示例

示例1:自定义注解处理器

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUser {}public class CurrentUserArgumentResolver implements HandlerMethodArgumentResolver {@Overridepublic boolean supportsParameter(MethodParameter parameter) {return parameter.hasParameterAnnotation(CurrentUser.class);}@Overridepublic Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {// 从安全上下文中获取当前用户return SecurityContextHolder.getContext().getAuthentication().getPrincipal();}
}

示例2:泛型类型处理器

public class GenericTypeProcessor {public void process(MethodParameter parameter) {ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter);if (resolvableType.getGeneric(0).resolve() == String.class) {System.out.println("第一个泛型参数是String类型");}}
}

高级用法

1. 嵌套泛型解析

public class Response<T> {private T data;// getter/setter
}public class UserController {public Response<List<User>> getUsers() { ... }
}// 解析嵌套泛型
MethodParameter returnParam = new MethodParameter(UserController.class.getMethod("getUsers"), -1);ResolvableType resolvableType = ResolvableType.forMethodParameter(returnParam);
Class<?> userType = resolvableType.getGeneric(0).getGeneric(0).resolve();
// userType == User.class

2. 参数名发现策略

如果编译时没有保留参数名信息(-parameters 编译选项),可以通过以下方式设置发现策略:

// 设置参数名发现器(基于ASM库)
parameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
String paramName = parameter.getParameterName();

常见问题解决

问题1:获取参数名返回null

解决方案

  1. 使用 Java 8+ 编译时添加 -parameters 选项

  2. 或者使用 ASM 库分析字节码:

parameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
String name = parameter.getParameterName();

问题2:泛型类型信息丢失

解决方案
使用 ResolvableType 代替直接获取 Class 对象:

// 不推荐 - 可能丢失泛型信息
Class<?> type = parameter.getParameterType();// 推荐 - 保留完整泛型信息
ResolvableType type = ResolvableType.forMethodParameter(parameter);

性能考虑

  1. 缓存 MethodParameter 实例
    MethodParameter 对象可以缓存重用,因为它们是线程安全的。

  2. 减少反射操作
    频繁调用 getParameterAnnotations() 等反射方法会影响性能,可以考虑缓存结果。

  3. 使用 ResolvableType 缓存
    ResolvableType 本身会缓存解析结果,无需额外处理。

总结

MethodParameter 是 Spring 框架中处理方法参数元数据的核心类,它提供了:

  • 完整的类型信息(包括泛型)

  • 注解访问能力

  • 参数名发现能力

  • 方法/构造器上下文信息

合理使用 MethodParameter 可以大大简化框架扩展开发,特别是在实现自定义参数解析器、返回值处理器等场景下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/76298.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt 5.14.2入门(一)写个Hello Qt!程序

目录 参考链接&#xff1a;一、新建项目二、直接运行三、修改代码增加窗口内容1、Qt 显示一个 QLabel 标签控件窗口2、添加按键 参考链接&#xff1a; Qt5教程&#xff08;一&#xff09;&#xff1a;Hello World 程序 Qt 编程指南 一、新建项目 1、新建一个项目&#xff08…

Spring Boot 3.x 集成 MongoDB 的 默认配置项及默认值,以及 常用需要修改的配置项 的详细说明

以下是 Spring Boot 3.x 集成 MongoDB 的 默认配置项及默认值&#xff0c;以及 常用需要修改的配置项 的详细说明&#xff1a; 一、默认配置项及默认值 Spring Boot 对 MongoDB 的默认配置基于 spring.data.mongodb 前缀&#xff0c;以下是核心配置项&#xff1a; 配置项默认…

【QT】 进程

目录 QT 多进程复习 Linux-C 多进程QProcess 进程类常用方法简单示例信号与槽应用场景 跨平台注意事项技巧&#xff1a;使用宏控制平台命令 QProcess 在嵌入式系统中的使用示例&#xff1a;调用 ALSA 播放音频示例&#xff1a;调用 arecord 录音示例&#xff1a;QProcess Shel…

原子操作(cpp atomic)

目录 一.原子操作 1.原子操作的概念 2.原子变量 二.原子性 1.中间状态描述 2.单处理器单核 3.多处理器或多核的情况下 4.cache&#xff08;高速缓冲器的作用&#xff09; 5.在cpu cache基础上,cpu如何读写数据&#xff1f;&#xff1f;&#xff1f; 6.为什么会有缓存…

Unet网络的Pytorch实现和matlab实现

文章目录 一、Unet网络简介1.1 输入图像1.2 编码器部分&#xff08;Contracting Path&#xff09;1.3 解码器部分&#xff08;Expanding Path&#xff09;1.4 最后一层&#xff08;输出&#xff09;1.5 跳跃连接&#xff08;Skip Connections&#xff09; 二、Unet网络的Pytorc…

记录一次JVM调优过程1

如何通过jmap 诊断&#xff0c;服务运行一段时间后内存使用量飙升的问题 通过 jmap 诊断服务运行一段时间后内存使用量飙升的问题&#xff0c;需结合堆转储分析、对象分布统计及工具链配合。以下是具体操作步骤和关键方法&#xff1a; 一、实时监控与初步分析 获取进程 PID 使…

接口自动化学习五:mock工具使用

Moco简介&#xff1a; Mock是一个简单搭建模拟服务器的框架&#xff0c;可以用来模拟http、https、socket等协议。 原理&#xff1a; Mock会根据一些配置&#xff0c;启动一个真正的HTTP服务&#xff08;会监听本地的某个端口&#xff09;,当发起的请求满足某个条件时&#xf…

若依 前后端部署

后端&#xff1a;直接把代码从gitee上拉去到本地目录 (https://gitee.com/y_project/RuoYi-Vue ) 注意下redis连接时password改auth 后端启动成功 前端&#xff1a;运行前首先确保安装了node环境&#xff0c;随后执行&#xff1a; &#xff01;&#xff01;一定要用管理员权限…

Adaptive AUTOSAR 状态管理和转换——ActionItemList

在AUTOSAR的状态转换管理(STM,State Transition Manager) 框架中,ActionItemList 是连接 状态机状态(State Machine State) 与 功能组状态(Function Group States) 的核心配置元素。 以下是其关系与作用的详细解释: 1. 核心概念 状态机状态(State Machine State) 表…

一个基于ragflow的工业文档智能解析和问答系统

工业复杂文档解析系统 一个基于ragflow的工业文档智能解析和问答系统,支持多种文档格式的解析、知识库管理和智能问答功能。 系统功能 1. 文档管理 支持多种格式文档上传(PDF、Word、Excel、PPT、图片等)文档自动解析和分块处理实时处理进度显示文档解析结果预览批量文档…

linux系统下如何提交git和调试

我们默认的ubuntu20.04镜像是没有Git提交的工具&#xff0c;我们需要配置安装包。 安装和更新git的命令 sudo apt update //用于更新软件包索引sudo apt install git //用于安装git版本控制工具 git --version //检查git版本,确认是否安装成功 随便进入linux系统下的一…

轻量级爬虫框架Feapder入门:快速搭建企业级数据管道

一、目标与前置知识 1. 目标概述 本教程的主要目标是&#xff1a; 介绍轻量级爬虫框架 Feapder 的基本使用方式。快速搭建一个采集豆瓣电影数据的爬虫&#xff0c;通过电影名称查找对应的电影详情页并提取相关信息&#xff08;电影名称、导演、演员、剧情简介、评分&#xf…

spring mvc的拦截器HandlerInterceptor 接口详解

HandlerInterceptor 接口详解 1. 接口方法说明 方法作用执行时机返回值/注意事项preHandle请求处理前拦截在控制器方法执行前调用返回 false 中断后续流程&#xff1b;返回 true 继续执行postHandle控制器方法执行后拦截在控制器方法返回结果后&#xff0c;视图渲染前调用无返…

数据可视化 —— 柱形图应用(大全)

一、案例一&#xff1a;单柱形图 1.导入库 import matplotlib.pyplot as plt import pandas as pd import numpy as np 2.给窗口名称和画布大小 plt.figure(num单柱形图, figsize(6, 4), facecolorw) 3.定义x、y轴的数据 # range(0-4) x np.arange(5) # 创建数组 y1 np.a…

apijson 快速上手

apijson是强大的工具&#xff0c;简化了CRUD的操作&#xff0c;只要有数据库表&#xff0c;就能自动生成RESTFUL接口。但初次上手也是摸索了很长时间&#xff0c;尤其是部署与使用上&#xff0c;这里尝试以初学者角度来说下&#xff1a; 一、好处 1、对于简单的应用&#xff…

V4L2杂谈

V4L2的开发手册 在做v4l2的开发的时候&#xff0c; 可以使用v4l2-ctl命令协助调试和软件开发。关于linux多媒体开发可以参考链接&#xff1a;https://www.linuxtv.org/wiki/index.php/Main_Page关于v4l2的api接口开发可以参考&#xff1a;https://linuxtv.org/docs.php在linux…

(五)深入了解AVFoundation-播放:多音轨、字幕、倍速播放与横竖屏切换

引言 在之前的博客中&#xff0c;我们已经实现了一个相对完整的播放器&#xff0c;具备了基本功能&#xff0c;如播放、暂停、播放进度显示和拖拽快进等。这为我们提供了一个坚实的基础。接下来&#xff0c;我们将进一步扩展播放器的功能&#xff0c;使其更具灵活性和实用性&a…

3ds Max 2016的版本怎么处理 按键输入被主程序截断 C#winform窗体接受不到英文输入

3ds Max 2016的版本怎么处理 按键输入被主程序截断 C#winform窗体接受不到英文输入 如果窗体失去焦点应该取消 全局监听事件 解决方案&#xff1a;在窗体失去焦点时取消全局键盘钩子 为了确保 WinForms 窗体失去焦点时不再拦截键盘事件&#xff08;避免影响 3ds Max 或其他程…

华为手机或平板与电脑实现文件共享

1.手机或平板与电脑在同一个网络 2.打开手机或平板端&#xff0c;设置---更多连接----快分享或华为分享打开此功能-----开启共享至电脑 3.打开电脑&#xff0c;网络中就可看到手机端分享的用户名称 4. 登陆就可访问手机 5.常见问题 5.1 电脑未发现本机 5.2 修改了访问密码后再…

elemenPlus中,如何去掉el-input中 文本域 textarea自带的边框和角标

1、去掉角标 :deep(.el-textarea__inner) {resize: none !important; // 去除右下角图标 }2、去除边框&#xff0c;并自定义背景色 <el-inputref"textareaRef"v-model"tempContent":style"{--el-border-color: rgba(255,255,255,0.0),--el-input-…