Spring中HandlerAdapter接口源碼解析
HandlerAdapter接口源碼
HandlerAdapter是一個適配器接口類,適配器模式是指兩個不兼容接口之間的橋梁,要想讓一個接口使用另外一個接口的實(shí)現(xiàn)中間可以加一層適配器類;舉個例子:筆記本沒有網(wǎng)線接口,那我想連接網(wǎng)線接通網(wǎng)絡(luò)如何實(shí)現(xiàn)呢?我可以買一個以太網(wǎng)轉(zhuǎn)換器,網(wǎng)線插入轉(zhuǎn)換器上,轉(zhuǎn)換器插入筆記本上就實(shí)現(xiàn)了連接網(wǎng)絡(luò)的功能,那這個轉(zhuǎn)換器起到的就是一個適配器的作用;在接口訪問控制器方法的時候是通過HandlerAdapter接口的實(shí)現(xiàn)類來進(jìn)行的,本文以最常用的RequestMappingHandlerAdapter適配器類為主線索來講解。
接口的源碼如下:
public interface HandlerAdapter { /** * 判定是否支持傳入的handler */ boolean supports(Object handler); /** * 使用給定的handler來處理當(dāng)前request請求 */ @Nullable ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; /** * 返回handler最后修改的時間 */ long getLastModified(HttpServletRequest request, Object handler); }
HandlerAdapter的實(shí)現(xiàn)類有多個,我們以RequestMappingHandlerAdapter適配器類為主線索,而此類又是AbstractHandlerMethodAdapter抽象類的子類;
如下是RequestMappingHandlerAdapter適配器類的關(guān)系圖
1.HandlerAdapter接口的初始化
容器加載時DispatcherServlet中的初始化方法initStrategies方法會被調(diào)用,里面的
/** * 容器中HandlerAdapter接口實(shí)現(xiàn)類集合 **/ @Nullable private List<HandlerAdapter> handlerAdapters; /** * 初始化handlerAdapters集合,如果在BeanFactory中沒有HandlerAdapter,那么將使用默認(rèn) * 的SimpleControllerHandlerAdapter */ private void initHandlerAdapters(ApplicationContext context) { this.handlerAdapters = null; //判定是否檢測所有的HandlerAdapter if (this.detectAllHandlerAdapters) { //查看容器中所有實(shí)現(xiàn)了HandlerAdapter的bean Map<String, HandlerAdapter> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerAdapters = new ArrayList<>(matchingBeans.values()); // We keep HandlerAdapters in sorted order. AnnotationAwareOrderComparator.sort(this.handlerAdapters); } } else { try { HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class); this.handlerAdapters = Collections.singletonList(ha); } catch (NoSuchBeanDefinitionException ex) { // Ignore, we'll add a default HandlerAdapter later. } } // Ensure we have at least some HandlerAdapters, by registering // default HandlerAdapters if no other adapters are found. if (this.handlerAdapters == null) { this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class); if (logger.isTraceEnabled()) { logger.trace("No HandlerAdapters declared for servlet '" + getServletName() + "': using default strategies from DispatcherServlet.properties"); } } }
上面的代碼是從容器中獲取HandlerAdapter接口實(shí)現(xiàn)類的bean集合
2.RequestMappingHandlerAdapter處理request請求
前端發(fā)送過來一個request請求首先進(jìn)入DispatcherServlet的doService方法,再進(jìn)入doDispatch方法,那我們看下doDispatch方法的源碼:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); //通過request請求獲取HandlerExecutionChain處理器執(zhí)行程序鏈 //也即通過request獲取匹配的HandlerMapping實(shí)現(xiàn)類,通過實(shí)現(xiàn)類的getHandler //方法獲取HandlerExecutionChain處理程序執(zhí)行器鏈類,里面包含了請求對應(yīng)的HandlerMethod //及對應(yīng)的所有攔截器 // Determine handler for the current request. mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } //根據(jù)上面獲取到的HandlerMethod獲取匹配到的適配器類 // Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } //根據(jù)適配器對象調(diào)用具體的方法(如:RequestMappingHandlerAdapter) // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
跳出本文分析的正文流程,來分析下AbstractHandlerMethodAdapter適配器類;
Abstract base class for {@link HandlerAdapter} implementations that support handlers of type {@link HandlerMethod}.
源碼注解說明類抽象類的實(shí)現(xiàn)support方法判定是否支持HandlerMethod;
/** * 判定適配器類是否支持HandlerMethod **/ @Override public final boolean supports(Object handler) { return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler)); }
getHandlerAdapter方法實(shí)現(xiàn)源碼:
/** * 獲取可以處理handler的HandlerAdapter適配器類 */ protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { for (HandlerAdapter adapter : this.handlerAdapters) { //判定適配器類是否支持HandlerMethod if (adapter.supports(handler)) { return adapter; } } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }
ha.handle(processedRequest, response, mappedHandler.getHandler());方法會調(diào)用AbstractHandlerMethodAdapter適配器類的handle方法:
@Override @Nullable public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); }
而handleInternal方法最終會調(diào)用RequestMappingHandlerAdapter類的handlerInternal方法:
@Override protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; checkRequest(request); // Execute invokeHandlerMethod in synchronized block if required. if (this.synchronizeOnSession) { HttpSession session = request.getSession(false); if (session != null) { Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // No HttpSession available -> no mutex necessary mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // No synchronization on session demanded at all... mav = invokeHandlerMethod(request, response, handlerMethod); } if (!response.containsHeader(HEADER_CACHE_CONTROL)) { if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { prepareResponse(response); } } return mav; }
handleInternal方法又會調(diào)用invokeHandlerMethod方法:
@Nullable protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response); try { WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); //創(chuàng)建HandlerMethod的子類ServletInvocableHandlerMethod的實(shí)例對象 ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); if (this.argumentResolvers != null) { //設(shè)置參數(shù)解析器 invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); } if (this.returnValueHandlers != null) { //設(shè)置返回值處理程序 invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); } invocableMethod.setDataBinderFactory(binderFactory); invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); ModelAndViewContainer mavContainer = new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response); asyncWebRequest.setTimeout(this.asyncRequestTimeout); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.setTaskExecutor(this.taskExecutor); asyncManager.setAsyncWebRequest(asyncWebRequest); asyncManager.registerCallableInterceptors(this.callableInterceptors); asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); if (asyncManager.hasConcurrentResult()) { Object result = asyncManager.getConcurrentResult(); mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0]; asyncManager.clearConcurrentResult(); LogFormatUtils.traceDebug(logger, traceOn -> { String formatted = LogFormatUtils.formatValue(result, !traceOn); return "Resume with async result [" + formatted + "]"; }); invocableMethod = invocableMethod.wrapConcurrentResult(result); } //調(diào)用ServletInvocableHandlerMethod類的invokeAndHandle方法 invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null; } return getModelAndView(mavContainer, modelFactory, webRequest); } finally { webRequest.requestCompleted(); } }
上面的方法會涉及到參數(shù)解析器的初始化、返回值處理程序的初始化,那這些返回值處理程序和參數(shù)解析程序如何初始化的呢?RequestMappingHandlerAdapter類實(shí)現(xiàn)了InitializingBean接口,該類加載后會調(diào)用afterPropertiesSet方法,會對這些處理程序進(jìn)行初始化;
@Override public void afterPropertiesSet() { // Do this first, it may add ResponseBody advice beans initControllerAdviceCache(); //參數(shù)解析器初始化 if (this.argumentResolvers == null) { List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers(); this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } //InitBinder的參數(shù)解析器初始化 if (this.initBinderArgumentResolvers == null) { List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers(); this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } //返回值處理程序初始化 if (this.returnValueHandlers == null) { List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers(); this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers); } }
調(diào)用ServletInvocableHandlerMethod.invokeAndHandle方法源碼如下:
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { //調(diào)用控制器方法,獲取返回值 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 { //將返回值交給HandlerMethodReturnValueHandlerComposite返回值代理類 //選擇合適的HandlerMethodReturnValueHandler實(shí)現(xiàn)類處理返回值 this.returnValueHandlers.handleReturnValue( returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } catch (Exception ex) { if (logger.isTraceEnabled()) { logger.trace(formatErrorForReturnValue(returnValue), ex); } throw ex; } }
調(diào)用InvocableHandlerMethod.invokeForRequest方法源碼:
/** * 獲取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); }
調(diào)用InvocableHandlerMethod.doInvoke(Object… args)方法源碼:
/** * 使用給定的參數(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); } } }
到此這篇關(guān)于Spring中HandlerAdapter接口源碼解析的文章就介紹到這了,更多相關(guān)HandlerAdapter接口源碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java?SpringBoot注解@Async不生效的解決方法
大家好,本篇文章主要講的是java?SpringBoot注解@Async不生效的解決方法,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下2022-01-01SpringMVC項(xiàng)目訪問controller時候報404的解決
這篇文章主要介紹了SpringMVC項(xiàng)目訪問controller時候報404的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09Spring?Data?Elasticsearch?5.x實(shí)現(xiàn)單詞糾錯和自動補(bǔ)全
這篇文章主要為大家介紹了Spring?Data?Elasticsearch?5.x實(shí)現(xiàn)單詞糾錯和自動補(bǔ)全示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08shiro并發(fā)人數(shù)登錄控制的實(shí)現(xiàn)代碼
在做項(xiàng)目中遇到這樣的需求要求每個賬戶同時只能有一個人登錄或幾個人同時登錄,如果是同時登錄的多人,要么不讓后者登錄,要么踢出前者登錄,怎么實(shí)現(xiàn)這樣的功能呢?下面小編給大家?guī)砹藄hiro并發(fā)人數(shù)登錄控制的實(shí)現(xiàn)代碼,一起看看吧2017-09-09Java應(yīng)用程序CPU100%問題排查優(yōu)化實(shí)戰(zhàn)
這篇文章主要介紹了如何排查和優(yōu)化Java應(yīng)用程序CPU使用率達(dá)到100%的問題,文中通過代碼示例和圖文結(jié)合的方式講解的非常詳細(xì),具有一定的參考價值,需要的朋友可以參考下2025-02-02Mybatis基礎(chǔ)概念與高級應(yīng)用小結(jié)
這篇文章主要介紹了Mybatis基礎(chǔ)回顧與高級應(yīng)用,本文內(nèi)容有點(diǎn)小長,希望大家耐心閱讀,此文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06