springMVC源码探索之RequestMappingHandlerMapping

导读:本篇文章讲解 springMVC源码探索之RequestMappingHandlerMapping,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

springMVC源码探索之RequestMappingHandlerMapping

简介

RequestMappingHandlerMapping是AbstractHandlerMethodMapping 抽象类的唯一实现类,它的作用 是根据在Controller中的@RequestMapping注解生成RequestMappingInfo。

方法

AbstractHandlerMethodMapping是抽象类这些方法的具体实现都在子类RequestMappingHandlerMapping 中。

detectHandlerMethods

AbstractHandlerMethodMapping#detectHandlerMethods() 这个方法的作用是从handler中获取handler method并注册。detectHandlerMethods 有些方法是需要RequestMappingHandlerMapping 实现的,相关方法会在下面介绍。

/**
 * Look for handler methods in a handler.
 * @param handler the bean name of a handler or a handler instance
 */
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);
                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);
                }

                // 为查找到的handler method 进行注册
                methods.forEach((method, mapping) -> {
                        Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
                        registerHandlerMethod(handler, invocableMethod, mapping);
                });
        }
}
复制代码

afterPropertiesSet

初始化bean是调用的方法,各种配置设置并调用父类afterPropertiesSet 方法。

@Override
public void afterPropertiesSet() {
// 各种配置设置
        this.config = new RequestMappingInfo.BuilderConfiguration();
        this.config.setUrlPathHelper(getUrlPathHelper());
        this.config.setPathMatcher(getPathMatcher());
        this.config.setSuffixPatternMatch(this.useSuffixPatternMatch);
        this.config.setTrailingSlashMatch(this.useTrailingSlashMatch);
        this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch);
        this.config.setContentNegotiationManager(getContentNegotiationManager());
        // 调用AbstractHandlerMethodMapping afterPropertiesSet 方法
        super.afterPropertiesSet();
}
复制代码

isHandler

isHandler 方法作用是判断提供的handler是否有@Controller或@RequestMapping注解

/**
	 * {@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));
	}
复制代码

getMappingForMethod

通过@RequestMapping 注解生成一个RequestMappingInfo 对象并返回,如果没有使用RequestMapping 注解会返回null,主要还是看createRequestMappingInfo 方法

@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;
}
复制代码

createRequestMappingInfo

createRequestMappingInfo 解析RequestMapping 注解 生成RequestMappingInfo对象。 createRequestMappingInfo(AnnotatedElement element)这个方法会先判断参数类型,然后根据类型去查找是否有额外的请求条件,如果有就把条件RequestMapping 和 条件做为参数调用重载方法 createRequestMappingInfo(RequestMapping requestMapping, @Nullable RequestCondition<?> customCondition);

private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
    RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
    // getCustomTypeCondition 和 getCustomMethodCondition return null 
    RequestCondition<?> condition = (element instanceof Class ?
                    getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
    return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
}
复制代码

getCustomTypeCondition和getCustomMethodCondition 这两个方法没有实现,它们的作用是自定义请求参数条件,如果需要可以继承AbstractRequestCondition 和使用CompositeRequestCondition 类来提供多个自定义条件。

重载方法createRequestMappingInfo,实际生成RequestMappingInfo 的方法,

/**
 * 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();
}
复制代码

上面就是简单的介绍了一下springmvc路径映射过程,有兴趣的还是看下源码吧,

能力有限,水平一般,如有错误,请多指出。

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/94654.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!