HandlerMapping初始化及调用源码分析

初始化
HandlerMapping
    -->AbstractHandlerMapping extends WebApplicationObjectSupport
        WebApplicationObjectSupport extends ApplicationObjectSupport
        ApplicationObjectSupport implements ApplicationContextAware(在容器初始化的时候会调用setApplicationContext方法,这个方法会调用initApplicationContext供子类进行初始化)
        @Override
        protected void initApplicationContext() throws BeansException {
            //空方法,供子类调用,目前springMVC中没有实现
            extendInterceptors(this.interceptors);
            //查找springMVC及父容器中的所有MappedInterceptort添加到List<HandlerInterceptor> adaptedInterceptors 中
            detectMappedInterceptors(this.adaptedInterceptors);
            //将List<Object> this.interceptors的内容判断是否为空,为空抛异常,不为空都add到List<HandlerInterceptor> adaptedInterceptors 中
            //老版本springMVC4.1.5的时候,还将MappedInterceptor和adaptedInterceptors分开存放,我现在看的是5.0.5是合在一起了(4.3.13也合在一起了)
            initInterceptors();
        }
        -->AbstractUrlHandlerMapping
            //注册处理器,如果handler是String类型的则从spring MVC容器中获取bean,判断相同路径下是否存在相同的处理器(判断与handlerMap中存在handler不同),存在抛异常
            //否则,按请求路径进行划分,如果是"/"则设置setRootHandler为当前的处理器,"/*"则setDefaultHandler为当前处理器,其他保存到 handlerMap 中
            protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {}
            -->SimpleUrlHandlerMapping
                这里的 urlMap 通过配置文件注册
                @Override
                public void initApplicationContext() throws BeansException {
                    super.initApplicationContext();
                    //注册处理器 Map<String, Object> urlMap
                    registerHandlers(this.urlMap);
                }

                protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
                    if (urlMap.isEmpty()) {
                        logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
                    }
                    else {
                        urlMap.forEach((url, handler) -> {
                            // Prepend with slash if not already present.
                            //路径不是一"/"开头的拼上"/"
                            if (!url.startsWith("/")) {
                                url = "/" + url;
                            }
                            // Remove whitespace from handler bean name.
                            if (handler instanceof String) {
                                handler = ((String) handler).trim();
                            }
                            //调用父类的 registerHandler
                            registerHandler(url, handler);
                        });
                    }
                }
            -->AbstractDetectingUrlHandlerMapping
                这里的 urlMap 通过查找容器中的bean的名称进行匹配
                @Override
                public void initApplicationContext() throws ApplicationContextException {
                    super.initApplicationContext();
                    detectHandlers();
                }
                protected void detectHandlers() throws BeansException {
                    ApplicationContext applicationContext = obtainApplicationContext();
                    if (logger.isDebugEnabled()) {
                        logger.debug("Looking for URL mappings in application context: " + applicationContext);
                    }
                    //获取所有的bean的名称
                    String[] beanNames = (this.detectHandlersInAncestorContexts ?
                            BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) :
                            applicationContext.getBeanNamesForType(Object.class));

                    // Take any bean name that we can determine URLs for.
                    //对每个beanName解析URL,如果能解析到就注册到 handlerMap
                    for (String beanName : beanNames) {
                        //调用子类方法
                        String[] urls = determineUrlsForHandler(beanName);
                        if (!ObjectUtils.isEmpty(urls)) {
                            // URL paths found: Let's consider it a handler.
                            registerHandler(urls, beanName);
                        }
                        else {
                            if (logger.isDebugEnabled()) {
                                logger.debug("Rejected bean name '" + beanName + "': no URL paths identified");
                            }
                        }
                    }
                }
                -->BeanNameUrlHandlerMapping
                //beanName或者alias(别名)是以"/"开头就符合要求
                @Override
                protected String[] determineUrlsForHandler(String beanName) {
                    List<String> urls = new ArrayList<>();
                    if (beanName.startsWith("/")) {
                        urls.add(beanName);
                    }
                    String[] aliases = obtainApplicationContext().getAliases(beanName);
                    for (String alias : aliases) {
                        if (alias.startsWith("/")) {
                            urls.add(alias);
                        }
                    }
                    return StringUtils.toStringArray(urls);
                }
        -->AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean
            //InitializingBean 接口会在容器初始化时调用 afterPropertiesSet 方法
            @Override
            public void afterPropertiesSet() {
                initHandlerMethods();
            }
            protected void initHandlerMethods() {
                if (logger.isDebugEnabled()) {
                    logger.debug("Looking for request mappings in application context: " + getApplicationContext());
                }
                //查找所有的beanName
                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);
                            }
                        }
                        //isHandler 方法判断该类是否有 Controller 或 RequestMapping 注解
                        if (beanType != null && isHandler(beanType)) {
                            detectHandlerMethods(beanName);
                        }
                    }
                }
                // 模板方法(空方法)供子类进行初始化,但子类目前没有实现
                handlerMethodsInitialized(getHandlerMethods());
            }
            protected void detectHandlerMethods(final Object handler) {
                //获取处理器类的类型
                Class<?> handlerType = (handler instanceof String ?
                        obtainApplicationContext().getType((String) handler) : handler.getClass());

                if (handlerType != null) {
                    //如果是cglib代理的子类型就返回父类型,其他返回传入的类型
                    final Class<?> userType = ClassUtils.getUserClass(handlerType);
                    //根据子类 RequestMappingInfoHandlerMapping 的继承关系,可以知道 T 表示的是 RequestMappingInfo
                    // RequestMappingInfo 保存的是 @RequestMapping 的7种条件信息
                    Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
                            (MethodIntrospector.MetadataLookup<T>) method -> {
                                try {
                                    //返回 RequestMappingInfo 如果方法没有 @RequestMapping 则返回 null
                                    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);
                    }
                    methods.forEach((method, mapping) -> {
                        //如果方法满足 Modifier.isPrivate(methodToUse.getModifiers()) && !Modifier.isStatic(methodToUse.getModifiers()) && SpringProxy.class.isAssignableFrom(targetType)
                        //抛异常
                        Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
                        registerHandlerMethod(handler, invocableMethod, mapping);
                    });
                }
            }
            protected void registerHandlerMethod(Object handler, Method method, T mapping) {
                this.mappingRegistry.register(mapping, handler, method);
            }
            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) {
                        // urlLookup 的map可以一个key对应多个value,因为相同的URL还可以根据其他条件判断
                        this.urlLookup.add(url, mapping);
                    }

                    String name = null;
                    if (getNamingStrategy() != null) {
                        // name 是类名的大写字母字符串+"#"+方法名,例 BaseController.logger() name就是BC#logger
                        name = getNamingStrategy().getName(handlerMethod, mapping);
                        addMappingName(name, handlerMethod);
                    }
                    //该方法直接返回null
                    CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
                    if (corsConfig != null) {
                        this.corsLookup.put(handlerMethod, corsConfig);
                    }
                    //Map<T, MappingRegistration<T>> registry 保存MappingRegistration信息,内容就是传入的参数
                    this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
                }
                finally {
                    this.readWriteLock.writeLock().unlock();
                }
            }
            -->abstract RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMapping<RequestMappingInfo>
                @Override
                @Nullable
                protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
                    // 获取注解的条件信息
                    RequestMappingInfo info = createRequestMappingInfo(method);
                    if (info != null) {
                        // 获取注解的条件信息,调用的是和上面一样的方法。这个获取的是类上注解的条件信息
                        RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
                        if (typeInfo != null) {
                            //将类上注解的条件信息和方法上注解的条件信息进行整合,类的条件在前
                            info = typeInfo.combine(info);
                        }
                    }
                    return info;
                }

                -->RequestMappingHandlerMapping
                // 如果不存在就返回 null
                @Nullable
                private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
                    //返回 RequestMapping 的注解信息
                    RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
                    //自定义的判断条件
                    // getCustomTypeCondition getCustomMethodCondition 两个方法在这个类中都直接返回null,感觉可以写子类复写这两个方法
                    RequestCondition<?> condition = (element instanceof Class ?
                            getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
                    //将 requestMapping 中的条件和自定义的条件一起放到 RequestMappingInfo 中并返回
                    return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
                }
调用
DispatcherServlet.doDispatch
    -->DispatcherServlet.getHandler
        -->AbstractHandlerMapping.getHandler
            -->AbstractHandlerMethodMapping.getHandlerInternal
-->AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
    String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
    if (logger.isDebugEnabled()) {
        logger.debug("Looking up handler method for path " + lookupPath);
    }
    this.mappingRegistry.acquireReadLock();
    try {
        HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
        if (logger.isDebugEnabled()) {
            if (handlerMethod != null) {
                logger.debug("Returning handler method [" + handlerMethod + "]");
            }
            else {
                logger.debug("Did not find handler method for [" + lookupPath + "]");
            }
        }
        // createWithResolvedBean 判断 handlerMethod 中的bean属性的值是否是String,如果是String就根据beanFactory获取bean,并新建 handleMatch 保存bean返回
        // 返回 bean 属性是bean对象的 handlerMethod
        return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
    }
    finally {
        this.mappingRegistry.releaseReadLock();
    }
}
@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
    List<Match> matches = new ArrayList<>();
    //根据URL获取匹配的 RequestMappingInfo
    List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
    if (directPathMatches != null) {
        //遍历 directPathMatches 获取到 RequestMappingInfo 再在 mappingLookup 中寻找对应的 handlerMethod,并将二者组合保存到 Match 对象中,并添加到 matches
        addMatchingMappings(directPathMatches, matches, request);
    }
    if (matches.isEmpty()) {
        // No choice but to go through all mappings...
        addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
    }

    if (!matches.isEmpty()) {
        //将符合条件的 Match 排序
        Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
        matches.sort(comparator);
        if (logger.isTraceEnabled()) {
            logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches);
        }
        Match bestMatch = matches.get(0);
        if (matches.size() > 1) {
            if (CorsUtils.isPreFlightRequest(request)) {
                return PREFLIGHT_AMBIGUOUS_MATCH;
            }
            Match secondBestMatch = matches.get(1);
            //如果第一个和第二个相同,则抛异常
            if (comparator.compare(bestMatch, secondBestMatch) == 0) {
                Method m1 = bestMatch.handlerMethod.getMethod();
                Method m2 = secondBestMatch.handlerMethod.getMethod();
                throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
                        request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
            }
        }
        //为request添加一些参数
        handleMatch(bestMatch.mapping, lookupPath, request);
        return bestMatch.handlerMethod;
    }
    else {
        return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
    }
}
private class Match {

    private final T mapping;

    private final HandlerMethod handlerMethod;

    public Match(T mapping, HandlerMethod handlerMethod) {
        this.mapping = mapping;
        this.handlerMethod = handlerMethod;
    }

    @Override
    public String toString() {
        return this.mapping.toString();
    }
}
public HandlerMethod createWithResolvedBean() {
    Object handler = this.bean;
    if (this.bean instanceof String) {
        Assert.state(this.beanFactory != null, "Cannot resolve bean name without BeanFactory");
        String beanName = (String) this.bean;
        handler = this.beanFactory.getBean(beanName);
    }
    return new HandlerMethod(this, handler);
}

猜你喜欢

转载自blog.csdn.net/u012562117/article/details/80424301