Spring中HandlerMethod類源碼詳細解析
HandlerMethod類
HandlerMethod類用于封裝控制器方法信息,包含類信息、方法Method對象、參數(shù)、注解等信息,具體的接口請求是可以根據(jù)封裝的信息調(diào)用具體的方法來執(zhí)行業(yè)務(wù)邏輯;
HandlerMethod有三個子類分別是InvocableHandlerMethod、ServletInvocableHandlerMethod、ConcurrentResultHandlerMethod,類的關(guān)系圖如下:

1.HandlerMethod類源碼詳解
public class HandlerMethod {
//bean名稱,調(diào)試的時候看到是字符串控制器名稱(首字母小寫)
private final Object bean;
//bean工廠類,個人調(diào)試傳入的是DefaultListableBeanFactory
@Nullable
private final BeanFactory beanFactory;
//方法所屬類
private final Class<?> beanType;
//控制器方法
private final Method method;
//橋接方法,如果method是原生的,這個屬性就是method
private final Method bridgedMethod;
//封裝方法參數(shù)實例
private final MethodParameter[] parameters;
//Http狀態(tài)碼
@Nullable
private HttpStatus responseStatus;
//ResponseStatus注解的reason值
@Nullable
private String responseStatusReason;
//使用createWithResolvedBean方法創(chuàng)建的HttpMethod方法對象
@Nullable
private HandlerMethod resolvedFromHandlerMethod;
//getInterfaceParameterAnnotations獲取
@Nullable
private volatile List<Annotation[][]> interfaceParameterAnnotations;
//類描述,使用initDescription方法解析beanType和method獲得
private final String description;
}
2.InvocableHandlerMethod類詳解
InvocableHandlerMethod類是HandlerMethod的直接子類,該類中新增了對請求參數(shù)解析的參數(shù)解析程序,request請求時的回調(diào)方法invokeForRequest和doInvoke(建議閱讀HandlerAdapter源碼解析)
request請求會在RequestMappingHandlerAdapter類中的handleInternal方法進行回調(diào),回調(diào)方法的源碼如下:
/**
* 獲取request請求參數(shù),調(diào)用控制器方法
**/
@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//獲取request請求方法的參數(shù)
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Arguments: " + Arrays.toString(args));
}
return doInvoke(args);
}
doInvoke方法源碼:
/**
* 使用給定的參數(shù)調(diào)用控制器方法
**/
@Nullable
protected Object doInvoke(Object... args) throws Exception {
ReflectionUtils.makeAccessible(getBridgedMethod());
try {
//調(diào)用真實最終的控制器方法,并返回執(zhí)行后的結(jié)果
return getBridgedMethod().invoke(getBean(), args);
}
catch (IllegalArgumentException ex) {
assertTargetBean(getBridgedMethod(), getBean(), args);
String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
throw new IllegalStateException(formatInvokeError(text, args), ex);
}
catch (InvocationTargetException ex) {
// Unwrap for HandlerExceptionResolvers ...
Throwable targetException = ex.getTargetException();
if (targetException instanceof RuntimeException) {
throw (RuntimeException) targetException;
}
else if (targetException instanceof Error) {
throw (Error) targetException;
}
else if (targetException instanceof Exception) {
throw (Exception) targetException;
}
else {
throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
}
}
}
3.ServletInvocableHandlerMethod類詳解
ServletInvocableHandlerMethod類繼承了InvocableHandlerMethod類,新增了處理返回值HandlerMethodReturnValueHandler的能力,并且新增了調(diào)用控制器方法的回調(diào)方法;
回調(diào)invokeAndHandle方法源碼如下:
/**
* Invoke the method and handle the return value through one of the
* configured {@link HandlerMethodReturnValueHandler HandlerMethodReturnValueHandlers}.
* @param webRequest the current request
* @param mavContainer the ModelAndViewContainer for this request
* @param providedArgs "given" arguments matched by type (not resolved)
*/
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//調(diào)用父類InvocableHandlerMethod的回調(diào)方法,并返回調(diào)用接口控制器方法的返回結(jié)果
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
setResponseStatus(webRequest);
if (returnValue == null) {
if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
disableContentCachingIfNecessary(webRequest);
mavContainer.setRequestHandled(true);
return;
}
}
else if (StringUtils.hasText(getResponseStatusReason())) {
mavContainer.setRequestHandled(true);
return;
}
mavContainer.setRequestHandled(false);
Assert.state(this.returnValueHandlers != null, "No return value handlers");
try {
//將控制器返回的結(jié)果交給HandlerMethodReturnValueHandler來處理
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(formatErrorForReturnValue(returnValue), ex);
}
throw ex;
}
}
4.ConcurrentResultHandlerMethod類詳解
ConcurrentResultHandlerMethod是ServletInvocableHandlerMethod的一個內(nèi)部類,也是它的子類,支持異常調(diào)用結(jié)果處理(暫時沒有發(fā)現(xiàn)使用的場景)
到此這篇關(guān)于Spring中HandlerMethod類源碼詳細解析的文章就介紹到這了,更多相關(guān)HandlerMethod類源碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于Java實現(xiàn)回調(diào)監(jiān)聽工具類
這篇文章主要為大家詳細介紹了如何基于Java實現(xiàn)一個回調(diào)監(jiān)聽工具類,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-04-04
Java實現(xiàn)音頻轉(zhuǎn)碼(WAV、MP3、AMR互轉(zhuǎn))
本文主要介紹了Java實現(xiàn)音頻轉(zhuǎn)碼,包括WAV、MP3、AMR互轉(zhuǎn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-02-02
java實現(xiàn)監(jiān)控rtsp流轉(zhuǎn)flv方法實例(前端播放,前后端代碼都有)
這篇文章主要給大家介紹了關(guān)于java實現(xiàn)監(jiān)控rtsp流轉(zhuǎn)flv的相關(guān)資料,文中介紹的是前端播放,前后端代碼都有,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-06-06
SSH框架網(wǎng)上商城項目第17戰(zhàn)之購物車基本功能
這篇文章主要為大家詳細介紹了SSH框架網(wǎng)上商城項目第17戰(zhàn)之購物車基本功能的實現(xiàn)過程,感興趣的小伙伴們可以參考一下2016-06-06
SpringBoot整合Ehcache3的實現(xiàn)步驟
本文主要介紹了SpringBoot整合Ehcache3的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01

