從DispatcherServlet說起,本文討論的內容都是DispatcherServlet的doDispatch方法完成
mappedHandler是一個HandlerExecutionChain,其中封裝了一個handler,和一個由interceptor組成的list
如果這張圖夠高,往下能看到handler是如何執行的,不過不是handler.execute()這樣的形式,而是由這樣的:
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
從注釋就可以看出,是通過反射的方式來調用,我已經看過一遍代碼了,實際上里面是通過找到Method的對象,進行的反射調用,重點就在於,這個Method對象是如何找到的
而找的這個過程,是包含在第一張圖中的下述方法調用里的:
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
這里使用的handlerAdapters是在private void initHandlerAdapters(ApplicationContext context)方法中得到初始化的,大致思想就是將所有實現了HandlerAdapter接口的類的實例都找出來放到這個list中
ha 是 AnnotationMethodHandlerAdapter 的實例時:執行上圖的邏輯
getMethodResolver的邏輯,已經執行執行中methodResolverCache的內容如上圖,可以看出里面是我們的handler對應的具體的Adapter對象
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
所以上面的ha實際上是比如:org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter@52d5661c
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
好吧,接着往下看,就是調用了,上面也提到過的,就是上面這段代碼
它里面是上面這樣,代碼挺多,但我只關心return invokeHandlerMethod(request, response, handler);
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ServletHandlerMethodResolver methodResolver = getMethodResolver(handler); Method handlerMethod = methodResolver.resolveHandlerMethod(request); ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver); ServletWebRequest webRequest = new ServletWebRequest(request, response); ExtendedModelMap implicitModel = new BindingAwareModelMap(); Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel); ModelAndView mav = methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest); methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest); return mav; }
上面就是具體的調用。看到這里,整個過程都結束了,已經返回了ModelAndView
但是但是但是但是,很多個但是。只有認真看了,或者像我一樣,嘗試學習這樣的實現,才會注意到很多細節。比如上面這個方法實際上只傳了一個handler進來,它怎么知道invoke哪個Method呢???
ServletHandlerMethodResolver methodResolver = getMethodResolver(handler); Method handlerMethod = methodResolver.resolveHandlerMethod(request);
重點就是上面這個methodResolver了,可以看到里面有一個mappings,存儲了被@requestMapping注解的方法,和注解的值這樣的一個對應關系
這是全文的重中之重
這個方法只有在服務器啟動后,第一次接受請求時,才能走到resolver = new ServletHandlerMethodResolver(handlerClass);后面的都是使用methodResolverCache了
上面的init實現如下
這里面很關鍵,但是很不起眼的代碼,竟然還被杠掉了,有空看看新的實現是什么,這段代碼就是:if (isHandlerMethod(specificMethod)),
這個方法是屬於AnnotationMethodHandlerAdapter類的,這個方法的參數就是Method,比如調試的時候是public java.lang.String com.test.springmvc.HelloWorld.hello()
上面這段代碼執行的時候,
mapping的內容是:
@org.springframework.web.bind.annotation.RequestMapping(name=, value=[/helloworld], path=[/helloworld], method=[], params=[], headers=[], consumes=[], produces=[])
patterns的內容是
[/helloworld]
所以this.mappings.put(method, mappingInfo);的結果是
{public java.lang.String com.test.springmvc.HelloWorld.hello()=[/helloworld]}
就這樣吧,明天來實現一把,當然不想按照它這個流程來,太復雜了,我最好簡化一下