RequestMappingHandlerMapping实现了InitializingBean接口,所以在实例化时会执行afterPropertiesSet()方法,源码如下:
@Override
public void afterPropertiesSet() {//requestMappingHandlerMapping类中方法
if (this.useRegisteredSuffixPatternMatch) {
this.fileExtensions.addAll(this.contentNegotiationManager.getAllFileExtensions());
}
super.afterPropertiesSet();//调用父类方法
}
super.afterPropertiesSet();此行代码调用父类AbstractHandlerMethodMapping中的如下代码,源码如下:
public void afterPropertiesSet() {
initHandlerMethods();
}
本类中initHandlerMethods();方法源码如下:
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);//侦查洞测HandlerMethods
}
}
handlerMethodsInitialized(getHandlerMethods());
}
如上代码释义:先获取所有的beanNames,然后根据beanNames循环遍历,如果isHandler(getApplicationContext().getType(beanName))方法为真执行detectHandlerMethods(beanName);
isHandler方法释义源码如下:
@Override
protected boolean isHandler(Class<?> beanType) {
return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) ||
(AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null));
}//表示bean上是否有Controller注解或RequestMapping注解,通过此俩注解表示此bean是否处理器bean
detectHandlerMethods(beanName);方法源码如下:
protected void detectHandlerMethods(final Object handler) {
Class<?> handlerType =
(handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass());
// Avoid repeated calls to getMappingForMethod which would rebuild RequestMatchingInfo instances
final Map<Method, T> mappings = new IdentityHashMap<Method, T>();//存放方法和对应的RequestMappingInfo,key为方法名称,value为RequestMappingInfo
final Class<?> userType = ClassUtils.getUserClass(handlerType);
Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() {
public boolean matches(Method method) {
T mapping = getMappingForMethod(method, userType);//为方法创造一个对应的requestMappingInfo类型的mapping
if (mapping != null) {
mappings.put(method, mapping);//以controller中的每个方法为key,以每个方法对应的requestMappingInfo为value,存入mappings中
return true;
}
else {
return false;
}
}
});
for (Method method : methods) {
registerHandlerMethod(handler, method, mappings.get(method));
}
}
如上代码释义:handlerType指我们的controller类型的值,如 class com.travelzen.tops.front.controller.PromotionController。
userType也是值controller。selectMethods方法是把controller的每个方法遍历出来并为每个方法封装一个requestMappingInfo放进map中,
最后注册handlerMethod,执行for循环中的此行代码,registerHandlerMethod(handler, method, mappings.get(method));源码如下:
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
HandlerMethod newHandlerMethod = createHandlerMethod(handler, method);//以处理器controller和其中的方法创建一个HandlerMethod
HandlerMethod oldHandlerMethod = this.handlerMethods.get(mapping);//已requestMappingInfo为参从handlerMethods中取出一个HandlerMethod
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);//以requestMappingInfo为key,和其对应的HandlerMethod为value存入handlerMethods中,方便以后取用
if (logger.isInfoEnabled()) {
logger.info("Mapped \"" + mapping + "\" onto " + newHandlerMethod);
}
Set<String> patterns = getMappingPathPatterns(mapping);//以requestMappingInfo为参获取patterns,其值就是url链接的值的形式,就是requestMappingInfo的value属性值,如: /compute/update,有多个时就是复数集合
for (String pattern : patterns) {
if (!getPathMatcher().isPattern(pattern)) {
this.urlMap.add(pattern, mapping);//循环遍历,如果pattern不存在符号*或?就放入urlMap中,其中pattern(pattern形如/compute/update)为key,mapping(例如 /compute/update对应requestMappingInfo)为value,方便以后取用
}
}
}
到此RequestMappingHandlerMapping初始化过程就算完成了。不对之处还望指正。
另补充一个重要的信息:
DispatcherServlet在启动时会根据配置文件创建HandlerMapping,这些HandlerMapping都实现了Ordered接口,DispatcherServlet实例化所有的HandlerMapping后放到一个集合中,并根据order对HandlerMapping进行排序。DispatcherServlet在接受请求时会循环遍历有序的HandlerMapping集合,RequestMappingHandlerMapping的order是0,开始接收请求。所以会以RequestMappingHandlerMapping这个处理器映射来处理请求而不是别的处理器映射。
参考:https://www.cnblogs.com/BINGJJFLY/p/7452717.html
https://my.oschina.net/zhangxufeng/blog/2177464
https://blog.youkuaiyun.com/weixin_34216196/article/details/91260441