这里主要以RequestMappingHandlerMapping和SimpleUrlHandlerMapping两个实现类进行初步的分析
HandlerMapping 继承关系
RequestMappingHandlerMapping 初始化
这个类处理spring MVC中用@RequestMapping标注的路径。
/**
* Return a {@link RequestMappingHandlerMapping} ordered at 0 for mapping
* requests to annotated controllers.
*/
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
mapping.setOrder(0);
mapping.setInterceptors(getInterceptors());
mapping.setContentNegotiationManager(mvcContentNegotiationManager());
mapping.setCorsConfigurations(getCorsConfigurations());
PathMatchConfigurer configurer = getPathMatchConfigurer();
Boolean useSuffixPatternMatch = configurer.isUseSuffixPatternMatch();
Boolean useRegisteredSuffixPatternMatch = configurer.isUseRegisteredSuffixPatternMatch();
Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch();
if (useSuffixPatternMatch != null) {
mapping.setUseSuffixPatternMatch(useSuffixPatternMatch);
}
if (useRegisteredSuffixPatternMatch != null) {
mapping.setUseRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch);
}
if (useTrailingSlashMatch != null) {
mapping.setUseTrailingSlashMatch(useTrailingSlashMatch);
}
UrlPathHelper pathHelper = configurer.getUrlPathHelper();
if (pathHelper != null) {
mapping.setUrlPathHelper(pathHelper);
}
PathMatcher pathMatcher = configurer.getPathMatcher();
if (pathMatcher != null) {
mapping.setPathMatcher(pathMatcher);
}
return mapping;
}
RequestMappingHandlerMapping 继承 AbstractHandlerMethodMapping< T> extends AbstractHandlerMapping implements InitializingBean
具体代码分析,查看HandlerMapping的初始化
//InitializingBean 接口会在容器初始化时调用 afterPropertiesSet 方法
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}
impleUrlHandlerMapping 初始化
@Bean
public SimpleUrlHandlerMapping faviconHandlerMapping() {
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
mapping.setUrlMap(Collections.singletonMap("**/favicon.ico",
faviconRequestHandler()));
return mapping;
}
impleUrlHandlerMapping 是通过initApplicationContext方法初始化的,具体代码分析,查看HandlerMapping的初始化
AbstractHandlerMapping extends WebApplicationObjectSupport
WebApplicationObjectSupport extends ApplicationObjectSupport
ApplicationObjectSupport implements ApplicationContextAware
(在容器初始化的时候会调用setApplicationContext方法,这个方法会调用initApplicationContext供子类进行初始化)
HandlerMapping 的初始化
下面内容是根据继承关系写的,查看时先找到具体实现类的初始化方法,在一步一步看
HandlerMapping
-->AbstractHandlerMapping extends WebApplicationObjectSupport
WebApplicationObjectSupport extends ApplicationObjectSupport
ApplicationObjectSupport implements ApplicationContextAware
(在容器初始化的时候会调用setApplicationContext方法,这个方法会调用initApplicationContext供子类进行初始化)
@Override
protected void initApplicationContext() throws BeansException {
//空方法,供子类调用,目前springMVC中没有实现
extendInterceptors(this.interceptors);
//查找springMVC及父容器中的所有MappedInterceptort添加到
//List<HandlerInterceptor> adaptedInterceptors 中
detectMappedInterceptors(this.adaptedInterceptors);
//将List<Object> this.interceptors的内容判断是否为空,为空抛异常,不为空都add到List<HandlerInterceptor> adaptedInterceptors 中
//老版本springMVC4.1.5的时候,还将MappedInterceptor和adaptedInterceptors分开存放,
//我现在看的是5.0.5是合在一起了(4.3.13也合在一起了)
initInterceptors();
}
-->AbstractUrlHandlerMapping
//注册处理器,如果handler是String类型的则从spring MVC容器中获取bean,
//判断相同路径下是否存在相同的处理器(判断与handlerMap中存在handler不同),存在抛异常
//否则,按请求路径进行划分,如果是"/"则设置setRootHandler为当前的处理器,
//"/*"则setDefaultHandler为当前处理器,其他保存到 handlerMap 中
protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {}
-->SimpleUrlHandlerMapping
这里的 urlMap 通过配置文件注册
@Override
public void initApplicationContext() throws BeansException {
super.initApplicationContext();
//注册处理器 Map<String, Object> urlMap
registerHandlers(this.urlMap);
}
protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
if (urlMap.isEmpty()) {
logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
}
else {
urlMap.forEach((url, handler) -> {
// Prepend with slash if not already present.
//路径不是一"/"开头的拼上"/"
if (!url.startsWith("/")) {
url = "/" + url;
}
// Remove whitespace from handler bean name.
if (handler instanceof String) {
handler = ((String) handler).trim();
}
//调用父类的 registerHandler
registerHandler(url, handler);
});
}
}
-->AbstractDetectingUrlHandlerMapping
这里的 urlMap 通过查找容器中的bean的名称进行匹配
@Override
public void initApplicationContext() throws ApplicationContextException {
super.initApplicationContext();
detectHandlers();
}
protected void detectHandlers() throws BeansException {
ApplicationContext applicationContext = obtainApplicationContext();
if (logger.isDebugEnabled()) {
logger.debug("Looking for URL mappings in application context: " + applicationContext);
}
//获取所有的bean的名称
String[] beanNames = (this.detectHandlersInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) :
applicationContext.getBeanNamesForType(Object.class));
// Take any bean name that we can determine URLs for.
//对每个beanName解析URL,如果能解析到就注册到 handlerMap
for (String beanName : beanNames) {
//调用子类方法
String[] urls = determineUrlsForHandler(beanName);
if (!ObjectUtils.isEmpty(urls)) {
// URL paths found: Let's consider it a handler.
registerHandler(urls, beanName);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Rejected bean name '" + beanName + "': no URL paths identified");
}
}
}
}
-->BeanNameUrlHandlerMapping
//beanName或者alias(别名)是以"/"开头就符合要求
@Override
protected String[] determineUrlsForHandler(String beanName) {
List<String> urls = new ArrayList<>();
if (beanName.startsWith("/")) {
urls.add(beanName);
}
String[] aliases = obtainApplicationContext().getAliases(beanName);
for (String alias : aliases) {
if (alias.startsWith("/")) {
urls.add(alias);
}
}
return StringUtils.toStringArray(urls);
}
-->AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean
//InitializingBean 接口会在容器初始化时调用 afterPropertiesSet 方法
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}
protected void initHandlerMethods() {
if (logger.isDebugEnabled()) {
logger.debug("Looking for request mappings in application context: " + getApplicationContext());
}
//查找所有的beanName
String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(obtainApplicationContext(), Object.class) :
obtainApplicationContext().getBeanNamesForType(Object.class));
for (String beanName : beanNames) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
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.isDebugEnabled()) {
logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
}
}
//isHandler 方法判断该类是否有 Controller 或 RequestMapping 注解
if (beanType != null && isHandler(beanType)) {
detectHandlerMethods(beanName);
}
}
}
// 模板方法(空方法)供子类进行初始化,但子类目前没有实现
handlerMethodsInitialized(getHandlerMethods());
}
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);
//根据子类 RequestMappingInfoHandlerMapping 的继承关系,
//可以知道 T 表示的是 RequestMappingInfo
// RequestMappingInfo 保存的是 @RequestMapping 的7种条件信息
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> {
try {
//返回 RequestMappingInfo 如果方法没有 @RequestMapping 则返回 null
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);
}
methods.forEach((method, mapping) -> {
//如果方法满足 Modifier.isPrivate(methodToUse.getModifiers()) &&
// !Modifier.isStatic(methodToUse.getModifiers()) &&
// SpringProxy.class.isAssignableFrom(targetType)
//抛异常 isAssignableFrom 表示targetType是否实现或继承SpringProxy
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
assertUniqueMethodMapping(handlerMethod, mapping);
if (logger.isInfoEnabled()) {
logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod);
}
this.mappingLookup.put(mapping, handlerMethod);
// 一个方法上可以配置多个路径
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
// urlLookup 的map可以一个key对应多个value,因为相同的URL还可以根据其他条件判断
this.urlLookup.add(url, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
// name 是类名的大写字母字符串+"#"+方法名,例 BaseController.logger() name就是BC#logger
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}
//该方法直接返回null
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
//Map<T, MappingRegistration<T>> registry 保存MappingRegistration信息,内容就是传入的参数
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
-->abstract RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMapping<RequestMappingInfo>
@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;
}
-->RequestMappingHandlerMapping
// 如果不存在就返回 null
@Nullable
private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
//返回 RequestMapping 的注解信息
RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
//自定义的判断条件
// getCustomTypeCondition getCustomMethodCondition 两个方法在这个类中都直接返回null,感觉可以写子类复写这两个方法
RequestCondition<?> condition = (element instanceof Class ?
getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
//将 requestMapping 中的条件和自定义的条件一起放到 RequestMappingInfo 中并返回
return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
}
HandlerMapping 调用
DispatcherServlet.doDispatch
-->DispatcherServlet.getHandler
-->AbstractHandlerMapping.getHandler
-->AbstractHandlerMethodMapping.getHandlerInternal
-->AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
if (logger.isDebugEnabled()) {
logger.debug("Looking up handler method for path " + lookupPath);
}
this.mappingRegistry.acquireReadLock();
try {
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
if (logger.isDebugEnabled()) {
if (handlerMethod != null) {
logger.debug("Returning handler method [" + handlerMethod + "]");
}
else {
logger.debug("Did not find handler method for [" + lookupPath + "]");
}
}
// createWithResolvedBean 判断 handlerMethod 中的bean属性的值是否是String,如果是String就根据beanFactory获取bean,并新建 handleMatch 保存bean返回
// 返回 bean 属性是bean对象的 handlerMethod
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
//根据URL获取匹配的 RequestMappingInfo
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
//遍历 directPathMatches 获取到 RequestMappingInfo 再在 mappingLookup 中寻找对应的 handlerMethod,并将二者组合保存到 Match 对象中,并添加到 matches
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
// No choice but to go through all mappings...
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
if (!matches.isEmpty()) {
//将符合条件的 Match 排序
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
matches.sort(comparator);
if (logger.isTraceEnabled()) {
logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches);
}
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
if (CorsUtils.isPreFlightRequest(request)) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
Match secondBestMatch = matches.get(1);
//如果第一个和第二个相同,则抛异常
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
Method m1 = bestMatch.handlerMethod.getMethod();
Method m2 = secondBestMatch.handlerMethod.getMethod();
throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
}
}
//为request添加一些参数
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
private class Match {
private final T mapping;
private final HandlerMethod handlerMethod;
public Match(T mapping, HandlerMethod handlerMethod) {
this.mapping = mapping;
this.handlerMethod = handlerMethod;
}
@Override
public String toString() {
return this.mapping.toString();
}
}
public HandlerMethod createWithResolvedBean() {
Object handler = this.bean;
if (this.bean instanceof String) {
Assert.state(this.beanFactory != null, "Cannot resolve bean name without BeanFactory");
String beanName = (String) this.bean;
handler = this.beanFactory.getBean(beanName);
}
return new HandlerMethod(this, handler);
}