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 ...
随机推荐
- INET_ADDRSTRLEN 和 INET6_ADDRSTRLEN 长度
在<netinet/in.h>中有这两个宏的定义 #define INET_ADDRSTRLEN 16 #define INET6_ADDRSTRLEN 46 INET_ADDRSTRLE ...
- 使用树莓派制作一套“NAS+私有云盘+下载机”
原创作者:HackLiu 0×00 前言 如果你家里有多台设备需要联网需要娱乐,你一定会或多或少遇到设备碎片化带来的烦恼.当然,已经有很多厂商包括新晋的小米.360在内的互联网公司 ...
- 【转】Visual Studio 2012常用快捷键总结
原文网址:http://blog.csdn.net/yl2isoft/article/details/9886379 写在前面: 都知道,合理使用快捷键可以提高开发效率.但是Visual Studio ...
- git Permissions 0777 for '/home/xxx/.ssh/id_rsa' are too open.
使用 git 时出现下面的问题,原因是 git 公钥的权限被修改了. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WAR ...
- 【linux】linux权限管理
一.权限的基本概念 权限:访问计算机资源或服务的访问能力. Linux中,每一个资源或者服务的权限, ...
- 闲扯淡笔记 - Web的历史
这里的Web指的是万维网,就是World Wide Web. 文档和静态资源 通过URL组织 Tim Berners Lee (TimBL) 于1989发明这个概念,这丫55年出生,和我父亲一般大. ...
- python 命令行参数获取
import argparse parser = argparse.ArgumentParser(description='Real-Time Filtering evaluation script ...
- opensuse下配置IP、DNS、GATEWAY
本人物理主机IP描述 IPv4 地址 . . . . . . . . . . . . : 192.168.1.101(首选)子网掩码 . . . . . . . . . . . . : 255.25 ...
- NHibernate ConfORM Mapping
前言 昨天写了一篇fluent nhibernate通过约定的代码映射方式,NH在3.0版本以后已经集成了conform的代码映射方式,一直没注意也没使用过,今天试试怎么样. 步骤 1.通过confo ...
- javascript如何判断手机端的浏览器是否支持触碰功能
if(document.hasOwnProperty("ontouchstart")) alert("浏览器支持触屏"); else alert("浏 ...