handler = controller = handlerMethod = Controller类里的一个方法抽象出来的实例

1. HandlerMethod执行目标方法类。

执行目标方法类共有3个: **非常重要!!
HandlerMethod、InvocableHandlerMethod、ServletInvocableHandlerMethod
其中HandlerMethod又是Handler的引用类型(即可以把HandlerMethod就看成Handler)**

0)继承关系

image.png

1)HandlerMethod —- handler

属性:有狠多,比如 bean(类型)、方法、方法参数(注意,这个很重要,是方法参数。)

image.png

行为:更多,比如,getMethodParam()、getBean(),getMethod()

即获取相关属性:得到方法参数,得到bean,得到方法,是否有方法注解

image.png

另外他还有两个内部类:返回值方法参数、处理方法参数(了解)

image.png
第一个类里面有几个有意思的操作:得到方法参数的注解、判断方法参数是否有某个注解image.pngimage.png

这个类竟然还有个继承体系

第二个类里面没啥重要的东西,最重要的就是一个可以获得返回值参数类型的操作image.pngimage.png

2)InvocableHandlerMethod

属性:resolvers、还有一个parameterNameDiscoverer(不知道啥用)

image.png

这里 handler和其方法参数解析器handlerMethodArgumentResolvers产生了联系。

行为:invokeForRequest() 、getMethodArgumentValues()。 第一个调用了第二个。

image.png
getMethodArgumentValues()作用1:返回装满了方法参数的数组。
image.png
getMethodArgumentValues()作用2:调用 方法参数解析器,使用的他的下面两个方法。将解析后的值赋给args[]。这里**handler和其方法参数解析器handlerMethodArgumentResolvers真正的产生了联系。 **
image.png

3)ServletInvocableHandlerMethod

属性:returnValueHandlers

image.png

行为:invokeAndHandle(),调用了InvocableHandlerMethod里的方法 其他的暂时用不着

image.png

2.MethodParameter:类

属性:参数、参数名字、参数注解、参数索引、参数类型

image.png

行为:获取方法、获取参数、获取参数类型、注解、名字等等

image.png

**

3.完整的调用逻辑

1.RequestMappingHandlerAdapter#invokeHandlerMethod()执行目标方法 -> 2.ServletInvocableHandlerMethod#invokeAndHandle() (此时完成了从handlerAdapter到handler的转移)-> 3.**InvocableHandlerMethod#invokeForRequest() 执行请求 ->
4.自身#getMethodArgumentValues() 目的是得到所有解析后的方法参数**
image.png

image.pngimage.pngimage.png
对4过程进行深究
调用HandlerMethod@**getMethodParameters()获取方法参数 ->
然后回过来用自身属性resolvers去解析当前参数
(这里调用HandlerMethodArgumentResolverComposite@resolveArgument()解析 ->
自身#**getArgumentResolver() 先获取合适的解析器 ->
用合适的解析器的**resolveArgument()去解析参数,返回解析后的值

最后回到InvocableHandlerMethod#invokeForRequest**()去激活args
image.png

**

4.重点类详解

1.HandlerMethodArgumentResolverComposite

作用:承载26种参数解析器和一个参数解析器缓存

image.pngimage.png

image.pngimage.png

2.ServletInvocableHandlerMethod

Invocable:调用、可调用的

此类的作用,装载argumentResolvers和returnValueHandlers 而且有个里面的invokeAndHandler()是真正的执行目标方法。


这个类有个 返回值处理器属性 image.png 操作:有个特别重要的操作 —-执行和处理 image.png

image.pngimage.pngimage.pngimage.pngimage.png

证明invokeAndHandler是真正的执行目标方法 image.pngimage.png 如上,点击下一个断点就能发现invokeForReques和setResponseStatus()之间先进入了ParameterTestController类里的方法。即执行目标方法。

想真正执行目标方法,必须确定目标方法里每一个参数的值。我们看看他是怎么确定的。

父类里的invokeForRequest()里有getMethodArgumentValue()
image.png

3.InvocableHandlerMethod

ServletInvocableHandlerMethod 的父类。 很多方法在ServletInvocableHandlerMethod里讲过

作用:得到目标的对象的参数,并对这些参数进行处理。

看一下这个类的属性,他有个 参数解析器的属性,正好是HandlerMethodArgumentResolverComposite类型,(猜想为什么会有这个属性,因为他其实是个handler,handler里面有方法参数,方法参数需要 参数解析器对其进行解析。) 操作:有两个特别重要的操作 —- 返回方法参数值、执行请求 。
image.pngimage.pngimage.png

image.pngimage.pngimage.pngimage.png
image.png
而HandlerMethod正好是handler的类型。即这里拿的其实就是handler的parameters。我们验证一下

debug,HandlerMethod#getMethodParameters()栈帧里的parameters
image.png
此时DispatcherServlet#doDispatch()的栈帧
image.png
发现,一模一样。

回到getMethodArgumentValues()上来,
image.png
这里的resolvers的类型就是
image.png
另外,别忘了这个类里有
image.png
resolvers里面有26个参数解析器和参数缓存。
image.png
判断26种解析器是否支持参数的具体过程:image.pngimage.png
这段代码的作用:遍历所有的26个参数解析器,看是否支持当前参数。
怎么判断是否支持?
image.png
比如第一个解析器是RequestParamMethod,进到他的supports方法发现,判断也很简单,看是否有RequestParam这个注解。
image.png
遍历的第二个是RequestParamMap,依旧是进去,supports方法,判断也是看是否有相应注解