springbank 开发日志 SpringMVC是如何找到handler找到对应的方法并执行的
从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]}
就这样吧,明天来实现一把,当然不想按照它这个流程来,太复杂了,我最好简化一下
springbank 开发日志 SpringMVC是如何找到handler找到对应的方法并执行的的更多相关文章
- springbank 开发日志 阅读spring mvc的源代码真是受益良多
决定模仿spring mvc的dispatcher->handlerMapping(return executorChain)->handler.execute 这样的流程之后,就开始看s ...
- springbank 开发日志 springbank是如何注册handler的
这要从DefaultAnnotationHandlerMapping这个类说起,该类被@Component注释,该类被Spring IOC容器实例化之后,将会执行其initApplicationCon ...
- springbank 开发日志 springbank是如何执行一个handler的requestMapping对应的方法的
占位 从dispatcher说起,方法doDispatch(Map request)的参数request是一个通过解析来报报文新城的map //获取HandlerExecutionChain,其中封装 ...
- springbank 开发日志 Spring启动过程中对自定义标签的处理
这篇随笔的许多知识来源于:http://www.importnew.com/19391.html 之所以会去看这些东东,主要是希望能够模仿spring mvc的处理流程,做出一套合理的交易处理流程. ...
- SpringBank 开发日志 使用maven构建dubbo服务的可执行jar包
写这篇日志的时候,我已经完成了这个目标,并且中间经历了一次面试.现在回过头看,已经觉得印象不那么深刻了,果然还是一边思考,一边记录这样最好.但我还是严格要求自己,从新做了梳理,对相关配置进行了整理和说 ...
- SpringBank 开发日志 Mybatis 使用redis 作为二级缓存时,无法通过cacheEnabled=false 将其关闭
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC ...
- SpringBank 开发日志 一种简单的拦截器设计实现
当交易由Action进入Service之前,需要根据不同的Service实际负责业务的不同,真正执行Service的业务逻辑之前,做一些检查工作.这样的拦截器应该是基于配置的,与Service关联起来 ...
- SpringBank 开发日志 重新设计Action调用Service的参数传递 使用泛型解决类型转换问题
之前想的比较简单,请求到达controller的时候,传给action的参数没有经过任何封装,就是一个Map.然后action再调用service的时候,传递的参数也是map @Controller ...
- springbank 开发日志 一次因为多线程问题导致的applicationContext.getBean()阻塞
几天前遇到的这个问题.由于交易是配置的,不同的交易是同一个类的不同实例,所以不可能提前将其以@autowired类似的方式注入到需要的类中 <op:transaction id="Re ...
随机推荐
- Ant基础知识2
Ant: 1.在windows上搭建Ant环境,成功后查看版本号 答案: (1)安装jdk,配置环境变量 (2)安装ant,配置环境变量,添加ANT_HOME,在path中加入%ANT_HOME%\b ...
- "飞机大战"游戏_Java
1 package cn.xiaocangtian.Util; import java.awt.Frame; import java.awt.Graphics; import java.awt.Ima ...
- Nginx 学习笔记(二)Web 服务启用 HTTP/2
个人网站提升为HTTP2.0协议,加速访问 一.条件 1.openssl的版本必须在1.0.2e及以上 2.nginx的版本必须在1.9.5以上 二.编译安装 1.openssl 编译安装 (1)开始 ...
- 绕过CDN查看网站真实IP的一些办法
验证是否存在CDN最简单的办法 通过在线的多地ping,通过每个地区ping的结果得到IP. 看这些IP是否一致,如果都是一样的,极大可能不存在cdn,但不绝对. 如果这些IP大多数都不太一样或者规律 ...
- MyBatis学习-入门
eclipse + jdk 1.8 + mybatis 1.数据库准备 安装mysql数据库,建立数据库test,在test库下建立测试的表 CREATE TABLE `t_user` ( `id` ...
- js中,for循环里面放ajax,ajax访问不到变量以及每次循环获取不到数据问题总结
想在点击"终端控制"的时候能够开启多个窗口对多个终端进行管理: /**提交事件**/ $("#terminalControl").bind("clic ...
- Struts S2-052漏洞利用
昨天在FreeBuf上看到[9月6日更新]漏洞预警 | 高危Struts REST插件远程代码执行漏洞(S2-052) 然而一直复现不了,今天又试了下竟然成功了. 由于水表查的较严,就不冒险搞别人的服 ...
- 【逆向知识】GitHub:Awesome-Hacking(黑客技能列表-逆向)
0 初衷 GitHub这一份黑客技能列表很不错,包含了多个方向的安全.但目前我关注只有逆向工程与恶意代码,所以其他的被暂时略过. 虽然很感谢作者的辛勤付出,但并不打算复制粘贴全套转载.逐条整理是为了从 ...
- 【vim】保存文件并退出 :w=:wq
这两个命令实际上并不完全等价,当文件被修改时两个命令时相同的.但如果未被修改,使用 :x 不会更改文件的修改时间,而使用 :wq 会改变文件的修改时间.
- ARMV8 datasheet学习笔记4:AArch64系统级体系结构之存储模型
1.前言 关于存储系统体系架构,可以概述如下: 存储系统体系结构的形式 VMSA 存储属性 2. 存储系统体系结构 2.1. 地址空间 指令地址空间溢出 指令地址计算((address_of ...