handler = controller = handlerMethod = Controller类里的一个方法抽象出来的实例
1. HandlerMethod执行目标方法类。
执行目标方法类共有3个: **非常重要!!
HandlerMethod、InvocableHandlerMethod、ServletInvocableHandlerMethod
其中HandlerMethod又是Handler的引用类型(即可以把HandlerMethod就看成Handler)**
0)继承关系
1)HandlerMethod —- handler
属性:有狠多,比如 bean(类型)、方法、方法参数(注意,这个很重要,是方法参数。)
行为:更多,比如,getMethodParam()、getBean(),getMethod()
即获取相关属性:得到方法参数,得到bean,得到方法,是否有方法注解
另外他还有两个内部类:返回值方法参数、处理方法参数(了解)
第一个类里面有几个有意思的操作:得到方法参数的注解、判断方法参数是否有某个注解
这个类竟然还有个继承体系
第二个类里面没啥重要的东西,最重要的就是一个可以获得返回值参数类型的操作
2)InvocableHandlerMethod
属性:resolvers、还有一个parameterNameDiscoverer(不知道啥用)
这里 handler和其方法参数解析器handlerMethodArgumentResolvers产生了联系。
行为:invokeForRequest() 、getMethodArgumentValues()。 第一个调用了第二个。
getMethodArgumentValues()作用1:返回装满了方法参数的数组。
getMethodArgumentValues()作用2:调用 方法参数解析器,使用的他的下面两个方法。将解析后的值赋给args[]。这里**handler和其方法参数解析器handlerMethodArgumentResolvers真正的产生了联系。 **
3)ServletInvocableHandlerMethod
属性:returnValueHandlers
行为:invokeAndHandle(),调用了InvocableHandlerMethod里的方法 其他的暂时用不着
2.MethodParameter:类
属性:参数、参数名字、参数注解、参数索引、参数类型
行为:获取方法、获取参数、获取参数类型、注解、名字等等
3.完整的调用逻辑
1.RequestMappingHandlerAdapter#invokeHandlerMethod()执行目标方法 -> 2.ServletInvocableHandlerMethod#invokeAndHandle() (此时完成了从handlerAdapter到handler的转移)-> 3.**InvocableHandlerMethod#invokeForRequest() 执行请求 ->
4.自身#getMethodArgumentValues() 目的是得到所有解析后的方法参数**
对4过程进行深究
调用HandlerMethod@**getMethodParameters()获取方法参数 ->
然后回过来用自身属性resolvers去解析当前参数
(这里调用HandlerMethodArgumentResolverComposite@resolveArgument()解析 ->
自身#**getArgumentResolver() 先获取合适的解析器 ->
用合适的解析器的**resolveArgument()去解析参数,返回解析后的值
)
最后回到InvocableHandlerMethod#invokeForRequest**()去激活args
**
4.重点类详解
1.HandlerMethodArgumentResolverComposite
作用:承载26种参数解析器和一个参数解析器缓存
2.ServletInvocableHandlerMethod
Invocable:调用、可调用的
此类的作用,装载argumentResolvers和returnValueHandlers 而且有个里面的invokeAndHandler()是真正的执行目标方法。
这个类有个 返回值处理器属性 操作:有个特别重要的操作 —-执行和处理
证明invokeAndHandler是真正的执行目标方法 如上,点击下一个断点就能发现invokeForReques和setResponseStatus()之间先进入了ParameterTestController类里的方法。即执行目标方法。
想真正执行目标方法,必须确定目标方法里每一个参数的值。我们看看他是怎么确定的。
父类里的invokeForRequest()里有getMethodArgumentValue()
3.InvocableHandlerMethod
ServletInvocableHandlerMethod 的父类。 很多方法在ServletInvocableHandlerMethod里讲过
作用:得到目标的对象的参数,并对这些参数进行处理。
看一下这个类的属性,他有个 参数解析器的属性,正好是HandlerMethodArgumentResolverComposite类型,(猜想为什么会有这个属性,因为他其实是个handler,handler里面有方法参数,方法参数需要 参数解析器对其进行解析。) 操作:有两个特别重要的操作 —- 返回方法参数值、执行请求 。
而HandlerMethod正好是handler的类型。即这里拿的其实就是handler的parameters。我们验证一下
debug,HandlerMethod#getMethodParameters()栈帧里的parameters
此时DispatcherServlet#doDispatch()的栈帧
发现,一模一样。
回到getMethodArgumentValues()上来,
这里的resolvers的类型就是
另外,别忘了这个类里有
resolvers里面有26个参数解析器和参数缓存。
判断26种解析器是否支持参数的具体过程:
这段代码的作用:遍历所有的26个参数解析器,看是否支持当前参数。
怎么判断是否支持?
比如第一个解析器是RequestParamMethod,进到他的supports方法发现,判断也很简单,看是否有RequestParam这个注解。
遍历的第二个是RequestParamMap,依旧是进去,supports方法,判断也是看是否有相应注解