资讯专栏INFORMATION COLUMN

SpringMvc 源码解读——AbstractHandlerMethodMapping系列

ninefive / 870人阅读

摘要:继承于继承于,其中系列是将作为来使用的,比如所注释的方法就是这种。的定义如下这里的其实就是在中注释的内容。系列的创建过程是实现了接口,所以容器会自动调用其方法,有交给方法完成具体的初始化。

RequestMappingHandlerMapping继承于RequestMappingInfoHandlerMapping继承于AbstractHandlerMethodMapping,其中AbstractHandlerMethodMapping系列是将method作为handler来使用的,比如@RequestMapping所注释的方法就是这种handler。AbstractHandlerMethodMapping里涉及的三个map。

/* java
private final Map handlerMethods = new LinkedHashMap();
private final MultiValueMap urlMap = new LinkedMultiValueMap();
private final MultiValueMap nameMap = new LinkedMultiValueMap();
*/

handlerMethods:保存着匹配条件(也就是RequestCondition)和Handler Method的对应关系,

urlMap:保存着URL与匹配条件的对应关系,当然这里的URL是pattern式的,可以使用通配符,另外,这里的map并不是普通的map,而是MultiValueMap,这是一种一个key对应多个值的Map,其实它的value是一个list类型的值。MultiValueMap的定义如下:public interface MultiValueMap extends Map>,这里的RequestCondition其实就是在@RequestMapping中注释的内容。

nameMap:这个Map是Spring MVC4新增的,保存着name和HandlerMethod的对应关系,它使用的是MultiValueMap类型的Map,也就是说一个name可以有多个HandlerMethod,这里的name是使用HandlerMethodMappingNamingStrategy策略的实现类从HandlerMethod中解析出来,默认使用RequestMappingInfoHandlerMethodMappingNamingStrategy实现类,解析规则是:类名里的大写字母+“#”+方法名

AbstractHandlerMethodMapping系列的创建过程是:AbstractHandlerMethodMapping实现了InitializingBean接口,所以Spring容器会自动调用其afterPropertiesSet方法,afterPropertiesSet有交给initHandlerMethods方法完成具体的初始化。

/* Java
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());
}

*/

首先拿到容器里所有的bean,然后跟住一定的规则筛选出来Handler,然后保存在map里,具体的筛选是在子类里,筛选的逻辑是检查类前是否有@Controller或者@RequestMapping注解。
紧接着,在detectHandlerMethods负责将Handler保存在Map里,detectHandlerMethods方法分两步走:首先从传入的处理器中找到符合要求的方法,然后用registerHandlerMethod进行注册(也就是保存在Map中),从这里可以看出Spring其实是将处理请求的方法所在的类看作处理器,而不是处理请求的方法,不过许多地方需要将请求的方法作为处理器来理解。从handler里获取可以处理请求的method的方法使用了HandlerMethodSelector.selectMethods,这个方法可以遍历传入的handler的所有方法,然后根据第二个MethodFilter类型的参数筛选出来合适的方法,这里的MethodFilter使用了匿名类,具体的判断逻辑是通过在匿名类里调用getMappingForMethod方法获取Method的匹配条件,如果可以获取,则认为是符合要求的,否则不符合要求,getMappingForMethod是模版方法,具体实现在RequestMappingHandlerMapping里,它是根据@RequestMapping注解来【匹配条件的,如果没有@RequestMapping注解则返回null,如果有,则根据注解的内容来创建RequestMappingInfo类型的匹配条件并返回。最后通过registerHandlerMethod的方法,注册到map中,在该方法中,首先检查一下handlerMethods这个map里是否已经有这个匹配条件了,如果有而且所对应的值和现在传入的handlerMethod不是同一个则抛出异常,否者依次添加到三个map里,再往nameMap里添加的时候需要现解析出name然后调用updateNameMap方法进行添加,通过put方法,进行覆盖式添加。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72594.html

相关文章

  • SpringMVC源码分析--HandlerMapping(六)

    摘要:概述上一节我们分析了的初始化过程,即创建并注册,本章我们分析下的请求处理过程,即查找。本系列文章是基于。最后创建了群方便大家交流,可扫描加入,同时也可加我,共同学习共同进步,谢谢 概述 上一节我们分析了RequestMappingHandlerMapping的初始化过程,即创建并注册HandlerMehtod,本章我们分析下RequestMappingHandlerMapping的请求...

    BDEEFE 评论0 收藏0
  • springMvc源码解读--HandlerMapping

    摘要:它的作用是根据找到相应的处理器和接口里面只有一个方法只要使用就会返回一个,当然我们可以定义自己的实现类来实现。 HandlerMapping:它的作用是根据request找到相应的处理器handler和interceptors,HandlerMapping接口里面只有一个方法HandlerExecutionChain getHandler(HttpServletRequest req...

    VishKozus 评论0 收藏0
  • SpringMvc源码解读--AbstractUrlHandlerMapping系列

    摘要:定义了一个变量,将所有的和的对应关系放在里面,最后注册在父类里面,创建时通过重写调用方法完成的注册,内部又调用父类的方法将我们注册的的注册到之中。 SimpleUrlHandlerMapping定义了一个map变量,将所有的URL和handler的对应关系放在里面,最后注册在父类里面,SimpleUrlHandlerMapping创建时通过重写initApplicationConte...

    mj 评论0 收藏0
  • SpringMVC源码分析--HandlerMapping(四)

    摘要:默认支持该策略。以上是对的宏观分析,下面我们进行内部细节分析。整体流程一通过实现接口,完成拦截器相关组件的初始化调用类的方法。总结本文主要分析了的初始化过程,希望对大家有帮助。随着学习的深入,后面有时间在分析下期中涉及的关键,比如等等。 概述 本节我们继续分析HandlerMapping另一个实现类ReqeustMappingHandlerMapping,该类是我们日常开发中使用最多的...

    imccl 评论0 收藏0
  • springMvc源码解读--AbstractUrlHandlerMapping

    摘要:系列都是继承于,它是通过来进行匹配的,是将与对应的保存在一个中,在方法中使用从中获取,中实现了具体用从中获取的过程,而将的初始化则交给了具体的子类去完成。这里的就是定义在中的,另外还单独定义了处理请求的处理器。 AbstractUrlHandlerMapping系列都是继承于AbstractUrlHandlerMapping,它是通过URL来进行匹配的,是将URL与对应的handler...

    dendoink 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<