? SpringtMVC中配置 <mvc:annotation-driven></mvc:annotation-driven> 与 <mvc:default-servlet-handler></mvc:default-servlet-handler> 源码解析_蜘蛛资讯网 yabo体育,亚博快速取款,亚博棋牌

丹麦生蚝泛滥成灾_SpringtMVC中配置 源码解析

上一篇有提到,当有、无这两个标签时,SpringtMVC 底层所采用的? HandlerMapping 以及 HandlerAdapter 是不一样的。现在就来进行源码调试,揭开 SpringtMVC 底层实现的庐山真面目。

??

Demo代码地址:?

?https://github.com/cyhbyw/springMVC_atguigu_TongGang

??工程名称:?

?springMVC_DebugSourceCode

?

现在开始调试。?

==============>>>>
PS:图片可能不是很清晰,可以右击图片、选择在新标签页中查看
或者,可以右击图片,选择“图片另存为”保存在本地并编好号(建议直接以01、02、03……来编号)
或者,可以右击图片,选择“复制图片”,再保存到本地并编好号(建议直接以01、02、03……来编号)
以上三种办法,任意选择喜欢的一种,以获得并查看更清晰的图片~~
<<<<==============

??

先来看看没有这两个标签的情况下,SpringMVC的行为吧。提示:需要在XML配置文件中注释掉这两个标签的内容!

01.?Bean定义文档的阅读器(其实就是读取XML配置文件中的内容);可以看到,SpringMVC?会读取到 component-scan?的元素,然后调用Line166的方法;注意线程堆栈信息,此方法位于 AbstractApplicationContext 的 Line501 的 refresh() 方法调用路径中(refresh() 方法是SpringIOC容器管理的核心方法,后面会再提及)

?

02.?解析元素;先调用 Line1339 的方法,再调用 Line1343 的方法;如图,Line1345 的 resolver()?方法很重要(后面详解)

?

03.?现在进入 resolve()?方法;然后调用 Line128 的 init() 方法

?

?

?04.?init() 方法就是注册一批Bean定义解析器;比如 Line35?就定义了 component-scan?元素的解析器

?

?

05.?注册的方式就是放入到 parsers?这个 map 中(这里放入,后面就会取出来使用)

?

?

06.?回到上一层,resolve()?方法处理完成后,调用 handler.parse()?方法

?

?

?07. parse()?方法会先去找对应元素的 parser

?

?

08.?找的本质其实就是从刚才的 map?中取出对应元素的值

?

?

09.?找到 parser?后,继续调用 parse()?方法

?

?

10. 继续调用

?

11. 继续调用

?

?

12. 下面两张图片中断点所在行的?beanDefs.add(registerPostProcessor 方法的?registerPostProcessor() 方法会依次被调用(可以理解,或者说,等价于 for 循环调用,只是 SpringtMVC 还有其它的判断逻辑)

?

13. 继续调用?registerBeanDefinition() 方法

?

?14. 通过 Line851 行将 beanName 添加到 beanDefinitionNames 中,以方便后续使用

??

?

15. 多次调用后,可以看到,beanDefinitionNames? 中的元素数量在增加

?

?16. XML 配置文件中定义的 component-scan 元素已经处理完成,现在继续处理 bean 元素(这是的 bean 元素其实是 XML 文件中定义的 InternalResourceViewResolver,只是没有为它的 id/name 赋值,所以下图中显示为 "bean: null")

?

?

17. 同理,InternalResourceViewResolver 会被添加到 beanDefinitionNames 中

?

?

18. 到目前为止,beanDefinitionNames 已经存入8个元素,是时候想想,什么时候会使用?beanDefinitionNames 了。

前面也提及过,AbstractApplicationContext 中有个 refresh() 方法,此方法是 SpringIOC 容器管理的核心方法,里面包含了对其它几个重要方法调用。

refresh() 方法非常重要!!!!

refresh() 方法非常重要!!!!

refresh() 方法非常重要!!!!

上面1--17步中方法的调用,其实都全部位于此处 Line501 的 obtainFreshBeanFactory() 方法中。现在,是时候转向其它方法的调用了。

调试发现,接下来 SpringtMVC 会走到 Line532 的 finishFresh() 方法。

?

?

19. 现在到达 DispatcherServlet 的 initStrategies() 方法;注意查看下图中的堆栈路径,有点多,不再详述了;同时,可以看到,此处 Line482 的 initHandlerMappings(context) & Line483 的 initHandlerAdapters(context) 方法其实就是从 context-->beanFactory-->beanDefinitionNames 中去获取 HandlerMapping & HandlerAdapter

?

?20. 不好意思,获取不到(这个很容易理解,因为上面我们看到的 beanDefinitionNames 确定没有任何一个 HandlerMapping 或者 HandlerAdapter),于是代码转到 Line588 去获取默认值

?

21. 默认值是从 defaultStrategies 中获取

?

?

22.?defaultStrategies 其实是采用 static{} 去读取 DispatcherServlet.properties 文件中的内容

?

23. 文件内容如下;默认两个 HandlerMapping 以及三个 HandlerAdapter (这就是没有配置这两个标签时 SpringtMVC 所采用的默认值)

?

?

24. 初始化 HandlerAdapter 的逻辑类似,不再详述

?

?

以上24步,是没有添加这两个标签时 SpringtMVC 的处理流程。接下来分析一下有这两个标签时的处理流程。

总体来说,大同小异,只是中间有个地方创建了不同的实例、然后调用了不用实例的方法、进而得到不同的Bean。

来具体看看吧。相同的逻辑不再赘述,下面的说明及配图主要体现在一些不同的点上。

?01.??现在开始处理 annotation-driven 元素

?

?02. 得到一个不同的 NamespaceHandler 并调用它的 init() 方法

?

?

03. 注册内容当然不一样;从图中可以明显看到,第一个就是 annotation-drivern 且对应的类是 AnnotationDrivenBeanDefinitionParser

?

?

04. 获取的时候,当然是拿到刚才注册进去的?AnnotationDrivenBeanDefinitionParser

?

?

05. parse() 方法自然也不一样;注意 Line204 行会注册 HANDLER_MAPPING_BEAN_NAME

?

?

06. 而这个?HANDLER_MAPPING_BEAN_NAME?其实就是 RequestMappingHandlerMapping

?

?

?07. 可以看到?RequestMappingHandlerMapping 已经被成功地添加到?beanDefinitionNames 中(那么,后续使用时,就可以取出它)

?

?

?08. 注册 HANDLER_ADAPTER_BEAN_NAME

?

09.?HANDLER_ADAPTER_BEAN_NAME 其实就是 RequestMappingHandlerAdapter

?

?

10. 将?RequestMappingHandlerAdapter 添加到?beanDefinitionNames 中(之后就可以使用啦~~)

?

?

?

简单总结起来就是:
1. 解析 annotation-driven 元素/标签
2. 根据 annotation-driven 创建 AnnotationDrivenBeanDefinitionParser 对象
3. AnnotationDrivenBeanDefinitionParser 中注册 RequestMappingHandlerMapping & RequestMappingHandlerAdapter 这两个 Bean
4. DispatcherServlet 中的 initStrategies 方法会分别调用 initHandlerMappings & initHandlerAdapters 方法从已经注册的 beanDefinitionNames 中初始化 HandlerMapping & HandlerAdapter
5. DispatcherServlet 中的 doDispatch 方法使用 HandlerMapping & HandlerAdapter

?

当前文章:http://www.kevincwu.com/99qqs9ls/27414-1297264-95414.html

发布时间:07:13:54

香港正版挂牌??本港台直播软件??今晚开什么特马资料??香港开奖结果现场直??香港马会现场直播开奖??六合财现场开奖??2019管家年婆一句诗中特??香港慈善网公开一肖??www.01804.com??香港马会本港台??

关于蜘蛛资讯网 | 蜘蛛资讯网动态 | 联系我们 | 法律声明 | 蜘蛛资讯网员工 | 蜘蛛资讯网邮箱 | 网站地图

蜘蛛资讯网版权所有