SpringMVC源码剖析2——处理器映射器
1.处理器映射器 HandlerMapping
一句话概括作用: 为 我 们 建 立 起 @RequestMapping 注 解 和 控 制 器 方 法 的 对 应 关 系 。
怎么去查看
第一步:
处理器映射器的实体类:
RequestMappingHandlerMapping
父类
RequestMappingInfoHandlerMapping
父类的父类
AbstractHandlerMethodMapping
父类的父类的父类
AbstractHandlerMapping
第二步:找到对应的方法,获取拦截的方法
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
public Map<T, HandlerMethod> getHandlerMethods() { this.mappingRegistry.acquireReadLock(); try { return Collections.unmodifiableMap(this.mappingRegistry.getMappings()); } finally { this.mappingRegistry.releaseReadLock(); }}getMappings()代码内容public Map<T, HandlerMethod> getMappings() { return this.mappingLookup;} |
<ignore_js_op>![]()
此处能看到一个无界HashMap,存储的是映射关系
那么什么时候存进去的呢?
在AbstractHandlerMethodMapping类中有如下代码:
扫描ApplicationContext中的bean,检测并注册处理程序方法。用来扫描bean的
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
protected void initHandlerMethods() { if (logger.isDebugEnabled()) { logger.debug("Looking for request mappings in application context: " + getApplicationContext()); } String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(obtainApplicationContext(), Object.class) : obtainApplicationContext().getBeanNamesForType(Object.class)); for (String beanName : beanNames) { if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { Class<?> beanType = null; try { beanType = obtainApplicationContext().getType(beanName); } catch (Throwable ex) { // An unresolvable bean type, probably from a lazy bean - let's ignore it. if (logger.isDebugEnabled()) { logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex); } } if (beanType != null && isHandler(beanType)) { detectHandlerMethods(beanName); } } } handlerMethodsInitialized(getHandlerMethods());} |
上述方法将扫描到的Colltroler类当做参数传递到下面的方法,通过反射获取.class字节码,然后再通过反射将方法和方法上面的路径找到存到map中
detectHandlerMethods(beanName);
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
protected void detectHandlerMethods(final Object handler) { Class<?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass()); if (handlerType != null) { final Class<?> userType = ClassUtils.getUserClass(handlerType); Map<Method, T> methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup<T>) method -> { try { return getMappingForMethod(method, userType); } catch (Throwable ex) { throw new IllegalStateException("Invalid mapping on handler class [" + userType.getName() + "]: " + method, ex); } }); if (logger.isDebugEnabled()) { logger.debug(methods.size() + " request handler methods found on " + userType + ": " + methods); } for (Map.Entry<Method, T> entry : methods.entrySet()) { Method invocableMethod = AopUtils.selectInvocableMethod(entry.getKey(), userType); T mapping = entry.getValue(); registerHandlerMethod(handler, invocableMethod, mapping); } }} |
registerHandlerMethod(handler, invocableMethod, mapping);
注册处理程序方法及其唯一映射。在启动时调用
|
1
2
3
|
protected void registerHandlerMethod(Object handler, Method method, T mapping) { this.mappingRegistry.register(mapping, handler, method);} |
先加锁,后将方法和映射放入Map中的
register(mapping, handler, method);
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
public void register(T mapping, Object handler, Method method) { this.readWriteLock.writeLock().lock(); try { HandlerMethod handlerMethod = createHandlerMethod(handler, method); assertUniqueMethodMapping(handlerMethod, mapping); if (logger.isInfoEnabled()) { logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod); } this.mappingLookup.put(mapping, handlerMethod); List<String> directUrls = getDirectUrls(mapping); for (String url : directUrls) { this.urlLookup.add(url, mapping); } String name = null; if (getNamingStrategy() != null) { name = getNamingStrategy().getName(handlerMethod, mapping); addMappingName(name, handlerMethod); } |
SpringMVC源码剖析2——处理器映射器的更多相关文章
- SpringMVC源码剖析(四)- DispatcherServlet请求转发的实现
SpringMVC完成初始化流程之后,就进入Servlet标准生命周期的第二个阶段,即“service”阶段.在“service”阶段中,每一次Http请求到来,容器都会启动一个请求线程,通过serv ...
- SpringMVC源码剖析(二)- DispatcherServlet的前世今生
上一篇文章<SpringMVC源码剖析(一)- 从抽象和接口说起>中,我介绍了一次典型的SpringMVC请求处理过程中,相继粉墨登场的各种核心类和接口.我刻意忽略了源码中的处理细节,只列 ...
- springMVC源码解析--ViewResolver视图解析器执行(三)
之前两篇博客springMVC源码分析--ViewResolver视图解析器(一)和springMVC源码解析--ViewResolverComposite视图解析器集合(二)中我们已经简单介绍了一些 ...
- springMVC源码解析--ViewResolverComposite视图解析器集合(二)
上一篇博客springMVC源码分析--ViewResolver视图解析器(一)中我们介绍了一些springMVC提供的很多视图解析器ViewResolver,在开发的一套springMVC系统中是可 ...
- springMVC源码分析--RequestParamMethodArgumentResolver参数解析器(三)
之前两篇博客springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)和springMVC源码解析--HandlerMethodArgumentResol ...
- springMVC源码解析--HandlerMethodArgumentResolverComposite参数解析器集合(二)
上一篇博客springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)中我们已经介绍了参数解析相关的东西,并且也提到了HandlerMethodArgume ...
- SpringMVC源码剖析1——执行流程
SpringMVC源码剖析1——执行流程 00.SpringMVC执行流程file:///C:/Users/WANGGA~1/AppData/Local/Temp/enhtmlclip/Image.p ...
- 《SpringMVC从入门到放肆》四、SpringMVC配置式开发(处理器映射器)
上一篇我们讲解了DispatcherServlet的url-pattern配置详解,今天我们来真正对SpringMVC进行配置式开发.所谓配置式开发是指“处理器类是程序员自己定义的.实现了特定接口的类 ...
- SpringMVC源码情操陶冶-InterceptorsBeanDefinitionParser拦截器解析器
解析mvc:interceptors节点 观察下InterceptorsBeanDefinitionParser的源码备注 /** * {@link org.springframework.beans ...
随机推荐
- Linux(CENTOS7) RabbitMq安装
RabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.它遵循Mozilla Public License开源协议,采用 Erlang 实现的工业级的消息队列(MQ)服务器,Rab ...
- CSS 选择器权重计算规则(转)
其实,CSS有自己的优先级计算公式,而不仅仅是行间>内部>外部样式:ID>class>元素. 一.样式类型 1.行间 <h1 style="font-size: ...
- Springboot注解--@Controller和@RestController的区别
1.使用@Controller 注解,在对应的方法上,视图解析器可以解析return 的jsp,html页面,并且跳转到相应页面:若返回json等内容到页面,则需要加@ResponseBody注解 2 ...
- Python合成GIF图片 -- imageio库
pip install imageio import imageio # 需要合在一起的图片 image_list = [r'C:\Users\Hlzy\Desktop\\' + str(x) + & ...
- 爬虫防止浏览器防止debug处理
方式一(基于你会前端,我比较喜欢这种方式) #复制html页面 #复制其中的js,css(css可有可无,如果加css和不加css情况不一样,网页可能做了css反爬处理) #全局搜索debug or ...
- Elasticsearch节点类型
当我们启动Elasticsearch的实例,就会启动至少一个节点.相同集群名的多个节点的连接就组成了一个集群. 在默认情况下,集群中的每个节点都可以处理http请求和集群节点间的数据传输,集群中所有的 ...
- 浅谈JVM - 内存结构(二)- 虚拟机栈|凡酷
2.1 定义 Java Virtual Machine Stacks(Java虚拟机栈) Java 虚拟机栈描述的是 Java 方法执行的内存模型,用于存储栈帧,是线程私有的,生命周期随着线程启动而产 ...
- python库文件下载地址(持续更新)
numpy https://pypi.org/project/numpy/#files PIL https://pypi.org/simple/pillow/ cv2 https://pypi.tun ...
- Maven--设置Http代理
<settings> ... <proxies> <proxy> <id>my-proxy</id> <active>true& ...
- js操作元素导致元素错位和大小改变
使用js循环的方式批量控制元素的大小时结果往往不尽如人意. 我总结了一条规律 在一个循环体内不可以同时存在一下两种操作,否则容易导致元素错位或大小改变: 1.对元素的offsetWidth.offse ...