spring 5.1.2 mvc HanderMapping源码

要须心地收汗马,孔孟行世目杲杲。这篇文章主要讲述spring 5.1.2 mvc HanderMapping源码相关的知识,希望能为你提供帮助。
RequestMappingHandlerMapping getMappingForMethod

/** * {@inheritDoc} * < p> Expects a handler to have either a type-level @{@link Controller} * annotation or a type-level @{@link RequestMapping} annotation. */ @Override protected boolean isHandler(Class< ?> beanType) { return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) || AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class)); }/** * Uses method and type-level @{@link RequestMapping} annotations to create * the RequestMappingInfo. * @return the created RequestMappingInfo, or {@code null} if the method * does not have a {@code @RequestMapping} annotation. * @see #getCustomMethodCondition(Method) * @see #getCustomTypeCondition(Class) */ @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); } String prefix = getPathPrefix(handlerType); if (prefix != null) { info = RequestMappingInfo.paths(prefix).build().combine(info); } } return info; }@Nullable String getPathPrefix(Class< ?> handlerType) { for (Map.Entry< String, Predicate< Class< ?> > > entry : this.pathPrefixes.entrySet()) { if (entry.getValue().test(handlerType)) { String prefix = entry.getKey(); if (this.embeddedValueResolver != null) { prefix = this.embeddedValueResolver.resolveStringValue(prefix); } return prefix; } } return null; }/** * Delegates to {@link #createRequestMappingInfo(RequestMapping, RequestCondition)}, * supplying the appropriate custom {@link RequestCondition} depending on whether * the supplied {@code annotatedElement} is a class or method. * @see #getCustomTypeCondition(Class) * @see #getCustomMethodCondition(Method) */ @Nullable private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) { RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class); RequestCondition< ?> condition = (element instanceof Class ? getCustomTypeCondition((Class< ?> ) element) : getCustomMethodCondition((Method) element)); return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null); }/** * Create a {@link RequestMappingInfo} from the supplied * {@link RequestMapping @RequestMapping} annotation, which is either * a directly declared annotation, a meta-annotation, or the synthesized * result of merging annotation attributes within an annotation hierarchy. */ protected RequestMappingInfo createRequestMappingInfo( RequestMapping requestMapping, @Nullable RequestCondition< ?> customCondition) {RequestMappingInfo.Builder builder = RequestMappingInfo .paths(resolveEmbeddedValuesInPatterns(requestMapping.path())) .methods(requestMapping.method()) .params(requestMapping.params()) .headers(requestMapping.headers()) .consumes(requestMapping.consumes()) .produces(requestMapping.produces()) .mappingName(requestMapping.name()); if (customCondition != null) { builder.customCondition(customCondition); } return builder.options(this.config).build(); }

【spring 5.1.2 mvc HanderMapping源码】AbstractHandlerMethodMapping implements InitializingBean
/** * Provide the mapping for a handler method. A method for which no * mapping can be provided is not a handler method. * @param method the method to provide a mapping for * @param handlerType the handler type, possibly a sub-type of the method‘s * declaring class * @return the mapping, or {@code null} if the method is not mapped */ @Nullable protected abstract T getMappingForMethod(Method method, Class< ?> handlerType); /** * Detects handler methods at initialization. * @see #initHandlerMethods */ @Override public void afterPropertiesSet() { initHandlerMethods(); }/** * Scan beans in the ApplicationContext, detect and register handler methods. * @see #getCandidateBeanNames() * @see #processCandidateBean * @see #handlerMethodsInitialized */ protected void initHandlerMethods() { for (String beanName : getCandidateBeanNames()) { if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { processCandidateBean(beanName); } } handlerMethodsInitialized(getHandlerMethods()); }/** * Determine the type of the specified candidate bean and call * {@link #detectHandlerMethods} if identified as a handler type. * < p> This implementation avoids bean creation through checking * {@link org.springframework.beans.factory.BeanFactory#getType} * and calling {@link #detectHandlerMethods} with the bean name. * @param beanName the name of the candidate bean * @since 5.1 * @see #isHandler * @see #detectHandlerMethods */ protected void processCandidateBean(String beanName) { 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.isTraceEnabled()) { logger.trace("Could not resolve type for bean ‘" + beanName + "‘", ex); } } if (beanType != null & & isHandler(beanType)) { detectHandlerMethods(beanName); } }/** * Look for handler methods in the specified handler bean. * @param handler either a bean name or an actual handler instance * @see #getMappingForMethod */ protected void detectHandlerMethods(Object handler) { Class< ?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass()); if (handlerType != null) { 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.isTraceEnabled()) { logger.trace("Mapped " + methods.size() + " handler method(s) for " + userType + ": " + methods); } methods.forEach((method, mapping) -> { Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); registerHandlerMethod(handler, invocableMethod, mapping); }); } }/** * Register a handler method and its unique mapping. Invoked at startup for * each detected handler method. * @param handler the bean name of the handler or the handler instance * @param method the method to register * @param mapping the mapping conditions associated with the handler method * @throws IllegalStateException if another method was already registered * under the same mapping */ protected void registerHandlerMethod(Object handler, Method method, T mapping) { this.mappingRegistry.register(mapping, handler, method); }


    推荐阅读