Spring中HandlerMethod類(lèi)源碼詳細(xì)解析
HandlerMethod類(lèi)
HandlerMethod類(lèi)用于封裝控制器方法信息,包含類(lèi)信息、方法Method對(duì)象、參數(shù)、注解等信息,具體的接口請(qǐng)求是可以根據(jù)封裝的信息調(diào)用具體的方法來(lái)執(zhí)行業(yè)務(wù)邏輯;
HandlerMethod有三個(gè)子類(lèi)分別是InvocableHandlerMethod、ServletInvocableHandlerMethod、ConcurrentResultHandlerMethod,類(lèi)的關(guān)系圖如下:
1.HandlerMethod類(lèi)源碼詳解
public class HandlerMethod { //bean名稱(chēng),調(diào)試的時(shí)候看到是字符串控制器名稱(chēng)(首字母小寫(xiě)) private final Object bean; //bean工廠(chǎng)類(lèi),個(gè)人調(diào)試傳入的是DefaultListableBeanFactory @Nullable private final BeanFactory beanFactory; //方法所屬類(lèi) private final Class<?> beanType; //控制器方法 private final Method method; //橋接方法,如果method是原生的,這個(gè)屬性就是method private final Method bridgedMethod; //封裝方法參數(shù)實(shí)例 private final MethodParameter[] parameters; //Http狀態(tài)碼 @Nullable private HttpStatus responseStatus; //ResponseStatus注解的reason值 @Nullable private String responseStatusReason; //使用createWithResolvedBean方法創(chuàng)建的HttpMethod方法對(duì)象 @Nullable private HandlerMethod resolvedFromHandlerMethod; //getInterfaceParameterAnnotations獲取 @Nullable private volatile List<Annotation[][]> interfaceParameterAnnotations; //類(lèi)描述,使用initDescription方法解析beanType和method獲得 private final String description; }
2.InvocableHandlerMethod類(lèi)詳解
InvocableHandlerMethod類(lèi)是HandlerMethod的直接子類(lèi),該類(lèi)中新增了對(duì)請(qǐng)求參數(shù)解析的參數(shù)解析程序,request請(qǐng)求時(shí)的回調(diào)方法invokeForRequest和doInvoke(建議閱讀HandlerAdapter源碼解析)
request請(qǐng)求會(huì)在RequestMappingHandlerAdapter類(lèi)中的handleInternal方法進(jìn)行回調(diào),回調(diào)方法的源碼如下:
/** * 獲取request請(qǐng)求參數(shù),調(diào)用控制器方法 **/ @Nullable public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { //獲取request請(qǐng)求方法的參數(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)用真實(shí)最終的控制器方法,并返回執(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類(lèi)詳解
ServletInvocableHandlerMethod類(lèi)繼承了InvocableHandlerMethod類(lèi),新增了處理返回值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)用父類(lèi)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來(lái)處理 this.returnValueHandlers.handleReturnValue( returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } catch (Exception ex) { if (logger.isTraceEnabled()) { logger.trace(formatErrorForReturnValue(returnValue), ex); } throw ex; } }
4.ConcurrentResultHandlerMethod類(lèi)詳解
ConcurrentResultHandlerMethod是ServletInvocableHandlerMethod的一個(gè)內(nèi)部類(lèi),也是它的子類(lèi),支持異常調(diào)用結(jié)果處理(暫時(shí)沒(méi)有發(fā)現(xiàn)使用的場(chǎng)景)
到此這篇關(guān)于Spring中HandlerMethod類(lèi)源碼詳細(xì)解析的文章就介紹到這了,更多相關(guān)HandlerMethod類(lèi)源碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring基于AspectJ的AOP開(kāi)發(fā)案例解析
這篇文章主要介紹了Spring的基于AspectJ的AOP開(kāi)發(fā),AspectJ是一個(gè)基于Java語(yǔ)言的AOP框架,使用AspectJ需要導(dǎo)入Spring?AOP和AspectJ相關(guān)jar包,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05Java設(shè)計(jì)模式之單例模式Singleton Pattern詳解
這篇文章主要介紹了Java設(shè)計(jì)模式之單例模式Singleton Pattern詳解,一些常用的工具類(lèi)、線(xiàn)程池、緩存,數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)連接池、賬戶(hù)登錄系統(tǒng)、配置文件等程序中可能只允許我們創(chuàng)建一個(gè)對(duì)象,這就需要單例模式,需要的朋友可以參考下2023-12-12import java和javax區(qū)別小結(jié)
Java包和javax包在Java編程語(yǔ)言中都起著至關(guān)重要的作用,本文就來(lái)介紹一下import java和javax區(qū)別小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下2024-10-10關(guān)于@EnableGlobalMethodSecurity注解的用法解讀
這篇文章主要介紹了關(guān)于@EnableGlobalMethodSecurity注解的用法解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03spring security中的默認(rèn)登錄頁(yè)源碼跟蹤
原來(lái)Spring Security有一個(gè)默認(rèn)的WebSecurityConfigurerAdapter,發(fā)現(xiàn)其中有一個(gè)init方法,于是在這個(gè)方法打了斷點(diǎn),在應(yīng)用啟動(dòng)的時(shí)候進(jìn)行跟蹤,這篇文章主要介紹了spring security之 默認(rèn)登錄頁(yè)源碼跟蹤,需要的朋友可以參考下2021-11-11淺析Java中SimpleDateFormat為什么是線(xiàn)程不安全的
SimpleDateFormat是Java中用于日期時(shí)間格式化的一個(gè)類(lèi),它提供了對(duì)日期的解析和格式化能力,本文主要來(lái)和大家一起探討一下SimpleDateFormat為什么是線(xiàn)程不安全的,感興趣的可以了解下2024-02-02Java inputstream和outputstream使用詳解
這篇文章主要介紹了Java inputstream和outputstream使用詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08Java 實(shí)現(xiàn)簡(jiǎn)易教務(wù)管理系統(tǒng)的代碼
這篇文章主要介紹了Java 實(shí)現(xiàn)簡(jiǎn)易教務(wù)管理系統(tǒng)的代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07