1.处理器映射器 HandlerMapping

一句话概括作用: 为 我 们 建 立 起 @RequestMapping 注 解 和 控 制 器 方 法 的 对 应 关 系 。

怎么去查看

第一步:

处理器映射器的实体类:
RequestMappingHandlerMapping   
父类  
RequestMappingInfoHandlerMapping
父类的父类
AbstractHandlerMethodMapping
父类的父类的父类
AbstractHandlerMapping

第二步:找到对应的方法,获取拦截的方法

[Java] 纯文本查看 复制代码
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的

[Java] 纯文本查看 复制代码
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);

[Java] 纯文本查看 复制代码
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);
注册处理程序方法及其唯一映射。在启动时调用

[Java] 纯文本查看 复制代码
1
2
3
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
   this.mappingRegistry.register(mapping, handler, method);
}

先加锁,后将方法和映射放入Map中的
register(mapping, handler, method);

[Java] 纯文本查看 复制代码
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——处理器映射器的更多相关文章

  1. SpringMVC源码剖析(四)- DispatcherServlet请求转发的实现

    SpringMVC完成初始化流程之后,就进入Servlet标准生命周期的第二个阶段,即“service”阶段.在“service”阶段中,每一次Http请求到来,容器都会启动一个请求线程,通过serv ...

  2. SpringMVC源码剖析(二)- DispatcherServlet的前世今生

    上一篇文章<SpringMVC源码剖析(一)- 从抽象和接口说起>中,我介绍了一次典型的SpringMVC请求处理过程中,相继粉墨登场的各种核心类和接口.我刻意忽略了源码中的处理细节,只列 ...

  3. springMVC源码解析--ViewResolver视图解析器执行(三)

    之前两篇博客springMVC源码分析--ViewResolver视图解析器(一)和springMVC源码解析--ViewResolverComposite视图解析器集合(二)中我们已经简单介绍了一些 ...

  4. springMVC源码解析--ViewResolverComposite视图解析器集合(二)

    上一篇博客springMVC源码分析--ViewResolver视图解析器(一)中我们介绍了一些springMVC提供的很多视图解析器ViewResolver,在开发的一套springMVC系统中是可 ...

  5. springMVC源码分析--RequestParamMethodArgumentResolver参数解析器(三)

    之前两篇博客springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)和springMVC源码解析--HandlerMethodArgumentResol ...

  6. springMVC源码解析--HandlerMethodArgumentResolverComposite参数解析器集合(二)

    上一篇博客springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)中我们已经介绍了参数解析相关的东西,并且也提到了HandlerMethodArgume ...

  7. SpringMVC源码剖析1——执行流程

    SpringMVC源码剖析1——执行流程 00.SpringMVC执行流程file:///C:/Users/WANGGA~1/AppData/Local/Temp/enhtmlclip/Image.p ...

  8. 《SpringMVC从入门到放肆》四、SpringMVC配置式开发(处理器映射器)

    上一篇我们讲解了DispatcherServlet的url-pattern配置详解,今天我们来真正对SpringMVC进行配置式开发.所谓配置式开发是指“处理器类是程序员自己定义的.实现了特定接口的类 ...

  9. SpringMVC源码情操陶冶-InterceptorsBeanDefinitionParser拦截器解析器

    解析mvc:interceptors节点 观察下InterceptorsBeanDefinitionParser的源码备注 /** * {@link org.springframework.beans ...

随机推荐

  1. iOS 蓝牙开发详解

    目前iOS智能硬件的开发交互方式主要分为两种,一种是基于低功耗的蓝牙4.0技术(由于耗电低,也称作为BLE(Bluetooth Low Energy))对应iOS的框架为CoreBluetooth,另 ...

  2. Transmission添加SSL访问

    0.准备工作 0.1.在App Center中安装Entware-ng 0.2.以admin用户登录SSH到NAS 0.3.申请SSL证书,可以找免费的申请一个 0.4.公网IP和域名,这个要和SSL ...

  3. 吴裕雄--天生自然TensorFlow高层封装:Estimator-DNNClassifier

    # 1. 模型定义. import numpy as np import tensorflow as tf from tensorflow.examples.tutorials.mnist impor ...

  4. numpy(二)

    1.集合操作 包含去重,交,并,差集操作 2.排序.搜索和计数 sort,where,argmin,argmax,count_nonzero,argwhere 3.线性代数 np.linalg库,包含 ...

  5. Oracle连接Navicat Premium遇到的问题

      ORA-28040: 没有匹配的验证协议. 通过查找资料找到了好的解决方案.可以不需要到官网上下载新的驱动来解决问题.    方法:在Oracle的安装路径下找到sqlnet.ora文件.(我的安 ...

  6. 关于Ueditor富文本编辑器的配置和使用心得

    一.环境和项目架构 本文章只是为了便于我个人记录日常笔记,如有错误或缺陷,请指出,文章仅供参考,如有转载请附上本文章链接. 介绍:将Ueditor富文本提交的内容直接生成Html文件,传到后台直接保存 ...

  7. Java连载72-String类详解、多个构造方法

    一.String类 1.String类是不可以变类,也就是说String对象声明后 2.java.lang.String:是字符串类型 (1)字符串一旦创建不可再改变,“abc”字符串对象一旦创建,不 ...

  8. LFW Face Database下载

    http://vis-www.cs.umass.edu/lfw/ Download the database: All images as gzipped tar file (173MB, md5su ...

  9. 吴裕雄--天生自然python Google深度学习框架:经典卷积神经网络模型

    import tensorflow as tf INPUT_NODE = 784 OUTPUT_NODE = 10 IMAGE_SIZE = 28 NUM_CHANNELS = 1 NUM_LABEL ...

  10. 吴裕雄--天生自然 PYTHON3开发学习:循环语句

    n = 100 sum = 0 counter = 1 while counter <= n: sum = sum + counter counter += 1 print("1 到 ...