您的位置:首页 > 移动开发

spring-mvc源码阅读(三)RequestMappingHandlerMapping

2013-10-28 22:23 381 查看
RequestMappingHandlerMapping主要有两个功能注册和查找
注册指的是注册Interceptor和controller
查找是根据request查找与之对应的controller和Interceptor
我们知道初始化DispatcherServlet的时候首先要初始化HandlerMapping,这个时候就会初始化spring容器中注册的HandlerMapping就是RequestMappingHandlerMapping
RequestMappingHandlerMapping的初始化主要分成两个部分
初始化Interceptor和controller
初始化的工作在AbstractHandlerMapping类中完成代码如下

protected void initApplicationContext() throws BeansException {
extendInterceptors(this.interceptors);
detectMappedInterceptors(this.mappedInterceptors);
initInterceptors();
}


完成了Interceptor的初始化后,就是controller的初始化
controller的初始化在AbstractHandlerMethodMapping中进行代码如下

protected void initHandlerMethods() {
if (logger.isDebugEnabled()) {
logger.debug("Looking for request mappings in application context: " + getApplicationContext());
}

String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
getApplicationContext().getBeanNamesForType(Object.class));

for (String beanName : beanNames) {
if (isHandler(getApplicationContext().getType(beanName))){
detectHandlerMethods(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}

protected boolean isHandler(Class<?> beanType) {
return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) ||
(AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null));
}


上面的代码中首先是找到spring容器中注册了的所有类的beamName
然后遍历这些类,检查它们是否是controller如果是则调用detectHandlerMethods方法代码如下

protected void detectHandlerMethods(final Object handler) {
Class<?> handlerType = (handler instanceof String) ?
getApplicationContext().getType((String) handler) : handler.getClass();

final Class<?> userType = ClassUtils.getUserClass(handlerType);

Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() {
public boolean matches(Method method) {
return getMappingForMethod(method, userType) != null;
}
});

for (Method method : methods) {
T mapping = getMappingForMethod(method, userType);
registerHandlerMethod(handler, method, mapping);
}
}
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo info = null;
RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
if (methodAnnotation != null) {
RequestCondition<?> methodCondition = getCustomMethodCondition(method);
info = createRequestMappingInfo(methodAnnotation, methodCondition);
RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
if (typeAnnotation != null) {
RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);
info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info);
}
}
return info;
}


在getMappingForMethod方法里面,找到方法里面的RequestMapping注解,然后根据注解生成RequestMappingInfo
完成上面的步骤之后,就会将找到的controller注册 代码如下

protected void registerHandlerMethod(Object handler, Method method, T mapping) {
HandlerMethod newHandlerMethod = createHandlerMethod(handler, method);
HandlerMethod oldHandlerMethod = handlerMethods.get(mapping);
if (oldHandlerMethod != null && !oldHandlerMethod.equals(newHandlerMethod)) {
throw new IllegalStateException("Ambiguous mapping found. Cannot map '" + newHandlerMethod.getBean()
+ "' bean method \n" + newHandlerMethod + "\nto " + mapping + ": There is already '"
+ oldHandlerMethod.getBean() + "' bean method\n" + oldHandlerMethod + " mapped.");
}

this.handlerMethods.put(mapping, newHandlerMethod);
if (logger.isInfoEnabled()) {
logger.info("Mapped \"" + mapping + "\" onto " + newHandlerMethod);
}

Set<String> patterns = getMappingPathPatterns(mapping);
for (String pattern : patterns) {
if (!getPathMatcher().isPattern(pattern)) {
this.urlMap.add(pattern, mapping);
}
}
}


这里面有两个map一个是urlMap,一个是handlerMethods
通过url我们可以找到与之对应的mapping,而通过mapping找到url对应的HandlerMethod 也就是要执行的controller和方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring-mvc 源码 阅读
相关文章推荐