Spring MVC之RequestMappingHandlerAdapter初始化
RequestMappingHandlerAdapter基于注解的处理器适配器,目的是用来执行handler,同时返回modelAndView给前端控制器,这块个人感觉是spring mvc的核心了,所以我会详细一些记录。
本篇文章先记录他初始化都做了什么。
先上类图:

通过类图可以看到,实现了InitializingBean接口,所以入口的方法就是 afterPropertiesSet();
下面来看代码:
public void afterPropertiesSet() {
List handlers;
if (this.argumentResolvers == null) { //加载默认的参数解析器
handlers = this.getDefaultArgumentResolvers();
this.argumentResolvers = (new HandlerMethodArgumentResolverComposite()).addResolvers(handlers);
}
if (this.initBinderArgumentResolvers == null) { //加载@initBinder注解的解析器
handlers = this.getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = (new HandlerMethodArgumentResolverComposite()).addResolvers(handlers);
}
if (this.returnValueHandlers == null) { //加载默认返回值的解析器
handlers = this.getDefaultReturnValueHandlers();
this.returnValueHandlers = (new HandlerMethodReturnValueHandlerComposite()).addHandlers(handlers);
}
this.initControllerAdviceCache(); //缓存 类有@ControllerAdvice 且@ModelAttribute 和 @InitBinder的注解的方法
}
注意:这些解析器实际上都是一个*****Composite结尾的包装类,实际上就是责任链模式的管理类,提供查找具体的解析器和执行方法,这块内容就不多描述了.
就拿参数解析器为例:
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList();
resolvers.add(new RequestParamMethodArgumentResolver(this.getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false)); //没有注解的pojo对象参数 使用它解析的
resolvers.add(new RequestResponseBodyMethodProcessor(this.getMessageConverters()));
resolvers.add(new RequestPartMethodArgumentResolver(this.getMessageConverters()));
resolvers.add(new RequestHeaderMethodArgumentResolver(this.getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(this.getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(this.getBeanFactory()));
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(this.getMessageConverters()));
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
resolvers.add(new MapMethodProcessor());
resolvers.add(new ErrorsMethodArgumentResolver());
resolvers.add(new SessionStatusMethodArgumentResolver());
resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
if (this.getCustomArgumentResolvers() != null) { //自定义的参数解析器
resolvers.addAll(this.getCustomArgumentResolvers());
} resolvers.add(new RequestParamMethodArgumentResolver(this.getBeanFactory(), true)); //据说全能的,有时间看下代码
resolvers.add(new ServletModelAttributeMethodProcessor(true));
return resolvers;
}
下面来看initControllerAdviceCache()方法
private void initControllerAdviceCache() {
if (this.getApplicationContext() != null) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Looking for controller advice: " + this.getApplicationContext());
}
//获取所有有@ControllerAdvice的Bean
List<ControllerAdviceBean> beans = ControllerAdviceBean.findAnnotatedBeans(this.getApplicationContext());
Collections.sort(beans, new OrderComparator());
Iterator i$ = beans.iterator();
while(i$.hasNext()) {
ControllerAdviceBean bean = (ControllerAdviceBean)i$.next(); //遍历bean拿到@ModelAttribute的方法
Set<Method> attrMethods = HandlerMethodSelector.selectMethods(bean.getBeanType(), MODEL_ATTRIBUTE_METHODS);
if (!attrMethods.isEmpty()) {
this.modelAttributeAdviceCache.put(bean, attrMethods); //缓存起来
this.logger.info("Detected @ModelAttribute methods in " + bean);
}
//拿到有@InitBinder的方法
Set<Method> binderMethods = HandlerMethodSelector.selectMethods(bean.getBeanType(), INIT_BINDER_METHODS);
if (!binderMethods.isEmpty()) {
this.initBinderAdviceCache.put(bean, binderMethods); //缓存起来
this.logger.info("Detected @InitBinder methods in " + bean);
}
}
}
}
到此为止,初始化完成
Spring MVC之RequestMappingHandlerAdapter初始化的更多相关文章
- Spring MVC之DispatcherServlet初始化详解
Spring作为一个优秀的web框架,其运行是基于Tomcat的.在我们前面的讲解中,Spring的驱动都是使用的ClassPathXmlApplicationContext,并且都是直接在main方 ...
- Spring MVC启动时初始化的几个常用方法
Spring-MVC的应用中,要实现类似的功能,主要是通过实现下面这些接口(任选一,至少一个即可) 一.ApplicationContextAware接口 +? 1 2 3 4 5 6 7 8 9 p ...
- Spring MVC(一)--SpringMVC的初始化和流程
SpringMVC是Spring提供给WEB应用的MVC框架,MVC框架一般来说由三部分组成: Model:模型层,一般由java bean完成,主要是进行数据库操作: View:视图层,用于前端展示 ...
- spring mvc之请求过程源码分析
简介 上一篇,我们分析了spring mvc启动过程的源码,这一节,来一起分析下在用户请求controller的过程中,spring mvc做了什么事? 一.准备 我写这么一个controller p ...
- Spring MVC组件之HandlerAdapter
Spring MVC组件之HandlerAdapter HandlerAdapter概述 HandlerAdapter组件是一个处理器Handler的适配器.HandlerAdapter组件的主要作用 ...
- 【WEB】初探Spring MVC框架
Spring MVC框架算是当下比较流行的Java开源框架.但实话实说,做了几年WEB项目,完全没有SpringMVC实战经验,乃至在某些交流场合下被同行严重鄙视“奥特曼”了.“心塞”的同时,只好默默 ...
- Spring MVC源码分析(续)——请求处理
转自:http://blog.csdn.net/shi1122/article/details/8041017 (转移位置了,时光隧道:http://www.jmatrix.org/spring/50 ...
- Spring MVC 实践 - Base
Spring MVC 实践 标签 : Java与Web Spring Web MVC Spring-Web-MVC是一种基于请求驱动的轻量级Web-MVC设计模式框架, Spring MVC使用MVC ...
- 《Spring技术内幕》笔记-第四章 Spring MVC与web环境
上下文在web容器中的启动 1,IoC容器的启动过程 IoC的启动过程就是建立上下文的过程.该上下文是与ServletContext相伴.在Spring中存在一个核心控制分发器,Dispatcher ...
随机推荐
- localhost能连接websocket 127.0.0.1 不能连接问题?
最近开发中遇到一个问题,就是有的浏览器电脑能连接websocket , 有的不能 , 有的能用localhost连接,有的能用127.0.0.1连接,这个问题很奇怪 提供一个很好测试websocket ...
- 《DSP using MATLAB》示例 Example 9.11
代码: %% ------------------------------------------------------------------------ %% Output Info about ...
- Armadillo安装及使用
以下转载自http://www.cnblogs.com/youthlion/archive/2012/05/15/2501465.html Armadillo是一个C++开发的线性代数库,在vs201 ...
- test20181024 ming
题意 分析 考场做法 考虑二分答案,R开到1e9就能过了. 判断答案合法,就判断时间和是否超过拥有的时间就行了.但要把di从小到大排序,不然容易验证贪心是错的. 时间复杂度\(O(n \log n)\ ...
- laravel 创建自定义全局函数
全局函数的实现是依靠在初始化的时候,将helps.php或者functions.php直接进行了加载.而Laravel中bootstrap/autoload.php(laravel 5.5 貌似没有这 ...
- sublime Text 3安装sublimecodeIntel插件
下载:https://github.com/SublimeCodeIntel/SublimeCodeIntel 解压到: data/pacakges目录 安装 Package Control插件 ...
- thinkpad t420安装debian需要注意的细节
关闭双显卡,使用集成显卡,32位可以用独显跑起来,但是64位的wheezy只能兼容集成显卡,不知道为啥,否则会在某些usb插入/或者拔出来以后,重启提示 failed to execute /lib/ ...
- redis与lua
内容大纲 redis里使用eval和evalsha redis管理Lua脚本 php里使用redis的lua脚本 在redis里使用lua脚本的好处 1.Lua脚本在Redis中是原子执行的,执行过 ...
- WPF学习基础
1. d:DesignHeight="300" d:DesignWidth="200": 分别指的是在vs设计界面的宽高,Width="500&quo ...
- java web 程序---注册页面核心代码哈希Map
收获:在运行程序的时候,错误出现.主要是map没有进行判断,是否为空,如果为空,则创建一个对象new HashMap(); 然后就注意细节, String name=request.getParame ...