springMVC源码探索之RequestMappingHandlerMapping
RequestMappingHandlerMapping
简介
RequestMappingHandlerMapping是AbstractHandlerMethodMapping 抽象类的唯一实现类,它的作用 是根据在Controller中的@RequestMapping注解生成RequestMappingInfo。
方法
上一篇在记录AbstractHandlerMethodMapping源码是有出现过一些方法,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路径映射过程,有兴趣的还是看下源码吧,
能力有限,水平一般,如有错误,请多指出。