1.前言
SpringMVC是目前J2EE平台的主流Web框架本文将通过源码(基于Spring4.3.7)分析,弄清楚Controller是如何匹配我们传入的参数,并定义简单的参数解析器
2.源码分析
doDispatch方法943行获取了HandlerAdapter,ctrl+h打开类继承图,找到RequestMappingHandlerAdapter,RequestMappingHandlerAdapter支持HandlerMethod的方法参数和返回类型,HandlerMethod是3.1版本引入的,为参数、返回值和注解提供便捷的封装
在RequestMappingHandlerAdapter的invokeHandlerMethod方法中,设置ArgumentResolver和ReturnValueHandler
798行和799行给RequestMappingHandlerAdapter定义的ArgumentResolver和ReturnValueHandler赋值,4.2版本以前在createRequstMapping方法,此方法在4.2已被删除
827行ServletInvocableHandlerMethod调用invokeAndHandle方法,通过定义的HandlerMethodReturnValueHandler处理返回值,点开invokeAndHandle方法进入ServletInvocableHandlerMethod类
116行处理通过HandlerMethodArgumentResolver来解析参数,132~133行使用注册过的HandlerMethodReturnValueHandler
afterPropertiesSet方法实现了InitializingBean接口初始化了Handler和Resolver,简单地说,启动服务才会运行afterPropertiesSet
517行设置ArgumentResolver,525行设置ReturnValueHandler
点看getDefaultArgumentResolvers方法,看看它到底做了什么
getDefaultArgumentResolvers方法把各种HandlerMethodArgumentResolver放入List并返回
同理,getDefaultReturnValueHandlers方法把各种HandlerMethodReturnValueHandler放入List并返回
现在在回到ServletInvocableHandlerMethod类,我们发现了returnValueHandlers是HandlerMethodReturnValueHandlerComposite类型的,神秘的HandlerMethodReturnValueHandlerComposite是什么?
查看类实现图,我们发现HandlerMethodReturnValueHandlerComposite继承HandlerMethodReturnValueHandler
我们可以看到,HandlerMethodReturnValueHandlerComposite类里有HandlerMethodReturnValueHandler类型的list,做过树结构的应该知道,这里用到了组合模式,即类包含自身对象组。但是呢,它的类名后面加上了Composite,不能严格意义上说是组合模式,可以说是组合模式的变种,因为HandlerMethodReturnValueHandler是个Interface,所以不是严格意义上的“组合模式”
我们用同样的思路寻找与HandlerMethodArgumentResolver对应的Composite类,我在ServletInvocableHandlerMethod没有找到HandlerMethodArgumentResolverComposite,(在4.3版本之前可以在ServletInvocableHandlerMethod找到),不用担心,使用绝招
快捷键ctrl+shift+r,用idea强大的全局搜索来找HandlerMethodArgumentResolverComposite的踪迹
这里注意一下,全局搜索选择Scope,才可以在文件所有路径下搜索(包括Maven源码包)
最后我们看到了HandlerMethodArgumentResolverComposite在InvocableHandlerMethod出现,这个类名觉得有些眼熟吧,它是ServletInvocableHandlerMethod的父类
ServletInvocableHandlerMethod调用InvocableHandlerMethod的invokeForRequest方法中使用了HandlerMethodArgumentResolverComposite
打开HandlerMethodArgumentResolverComposite,和HandlerMethodReturnValueHandlerComposite类似,使用组合模式的变种
好了,参数解析基本流程完毕,我们现在来具体看看支持和参数相映射的注解的参数解析类,对着HandlerMethodArgumentResolver按ctrl+h