深入理解 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.pswp.cn/pingmian/76298.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/76298.shtml
英文地址,請注明出處:http://en.pswp.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-…