spring MVC RequestMappingHandlerMapping解析
getHandler(HttpServletRequest request)
在doDispatch(HttpServletRequest request, HttpServletResponse response)
中,调用过getHandler(HttpServletRequest request)
。
DispatcherServlet)的getHandler(HttpServletRequest request方法,该方法遍历所有HandlerMapping并找到匹配的HandlerExecutionChain并返回HandlerExecutionChain对象。源码如下:
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
//遍历HandlerMapping
for (HandlerMapping mapping : this.handlerMappings) {
//找到匹配的HandlerExecutionChain
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
HandlerExecutionChain
我们打开HandlerExecutionChain看一下,发现他是一个包含Handler(我们平时叫Handler,后面你会发现其实他是HandlerMethod的子类)和HandlerInterceptor。
根据源码的注释,我们可以得知这个HandlerExecutionChain是一个调用执行链,包含了HandlerInterceptor和handler。
/**
* Handler execution chain, consisting of handler object and any handler interceptors.
* Returned by HandlerMapping's {@link HandlerMapping#getHandler} method.
*
* @author Juergen Hoeller
* @since 20.06.2003
* @see HandlerInterceptor
*/
public class HandlerExecutionChain {
private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
//handler
private final Object handler;
//HandlerInterceptor数组
@Nullable
private HandlerInterceptor[] interceptors;
//HandlerInterceptor的List
@Nullable
private List<HandlerInterceptor> interceptorList;
//interceptor的下标,应该是代表执行到哪一个HandlerInterceptor
private int interceptorIndex = -1;
RequestMappingHandlerMapping
HandlerMapping是一个接口,HandlerMapping的实现类是有十分多的,RequestMappingHandlerMapping
类做为重点介绍。根据RequestMappingHandlerMapping的注释,该类用于创建@RequestMapping和@Controller注解的实例。
RequestMappingHandlerMapping的初始化
找到RequestMappingHandlerMapping的afterPropertiesSet()
方法,这个方法来自InitializingBean接口,根据Bean的生命周期可以知道,当做完bean属性填充之后我们会调用InitializingBean.afterPropertiesSet()
@Override
@SuppressWarnings("deprecation")
public void afterPropertiesSet() {
//创建RequestMappingInfo.BuilderConfiguration对象,创建配置信息用
this.config = new RequestMappingInfo.BuilderConfiguration();
//调用setter设置各种属性
this.config.setUrlPathHelper(getUrlPathHelper());
this.config.setPathMatcher(getPathMatcher());
this.config.setSuffixPatternMatch(useSuffixPatternMatch());
this.config.setTrailingSlashMatch(useTrailingSlashMatch());
this.config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch());
this.config.setContentNegotiationManager(getContentNegotiationManager());
//调用父类AbstractHandlerMethodMapping的afterPropertiesSet()
super.afterPropertiesSet();
}
找到AbstractHandlerMethodMapping(一个抽象类)的afterPropertiesSet()。我讲一下,这个afterPropertiesSet()做了什么操作,代码有点长,但是核心操作就几个:
- 调用getCandidateBeanNames()从上下文中扫描合适的bean,并获取候选bean的名字(@Controller注解的bean)
- 调用
processCandidateBean(String beanName)
从上下文中获取对应beanName的beanType,并将beanType传递给isHandler(Class<?> beanType) - isHandler(Class<?> beanType)判断是否@RequestMapping和@Controller注解的实例
- 经过
isHandler(Class<?> beanType)
过滤的beanName会并将符合要求的beanName丢给detectHandlerMethods(Object handler)
方法处理。 detectHandlerMethods(Object handler)
会找处指定的handler bean中的handler methods(符合的@RequestMapping注解过的方法),并调用registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping)
去注册方法- 调用getHandlerMethods(),获取从this.mappingRegistry获取HandlerMethods
- 最后调用handlerMethodsInitialized()作一些初始化后的日志工作
因为调用方法比较多,我分开展示:
initHandlerMethods()
/**
* Detects handler methods at initialization.
* @see #initHandlerMethods
*/
@Override
public void afterPropertiesSet() {
//去调用下面的initHandlerMethods()
initHandlerMethods();
}
/**
* Scan beans in the ApplicationContext, detect and register handler methods.
* @see #getCandidateBeanNames()
* @see #processCandidateBean
* @see #handlerMethodsInitialized
*/
protected void initHandlerMethods() {
//getCandidateBeanNames()从上下文中扫描合适的bean的名字
for (String beanName : getCandidateBeanNames()) {
//必须不带“scopedTarget.”前缀的bean名
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
//发现并注册handler methods
processCandidateBean(beanName);
}
}
//handlerMethodsInitialized()只是日志工作
//getHandlerMethods()
handlerMethodsInitialized(getHandlerMethods());
}
getCandidateBeanNames()
中上下文中获取候选的bean
/**
* Determine the names of candidate beans in the application context.
* @since 5.1
* @see #setDetectHandlerMethodsInAncestorContexts
* @see BeanFactoryUtils#beanNamesForTypeIncludingAncestors
*/
//从上下文中扫描合适的bean的名字
protected String[] getCandidateBeanNames() {
return (this.detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(obtainApplicationContext(), Object.class) :
obtainApplicationContext().getBeanNamesForType(Object.class));
}
processCandidateBean(String beanName)
/**
* Determine the type of the specified candidate bean and call
* {@link #detectHandlerMethods} if identified as a handler type.
* <p>This implementation avoids bean creation through checking
* {@link org.springframework.beans.factory.BeanFactory#getType}
* and calling {@link #detectHandlerMethods} with the bean name.
* @param beanName the name of the candidate bean
* @since 5.1
* @see #isHandler
* @see #detectHandlerMethods
*/
//发现并注册handler methods
protected void processCandidateBean(String beanName) {
Class<?> beanType = null;
try {
//从上下文中获取对应beanName的bean的Type
beanType = obtainApplicationContext().getType(beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isTraceEnabled()) {
logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
}
}
//使用isHandler(Class<?> beanType)过滤符合要求的Handler
if (beanType != null && isHandler(beanType)) {
//发现HandlerMethod,最终会调用父类方法注册到this.mappingRegistry中
detectHandlerMethods(beanName);
}
}
isHandler(Class<?> beanType)
判断哪些是符合要求的Handler
//判断哪些是符合要求的Handler,从该方法可以得知要的是@Controller和@RequestMapping的bean
@Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
detectHandlerMethods(Object handler)
发现HandlerMethod,最终会调用父类方法注册到this.mappingRegistry中
/**
* Look for handler methods in the specified handler bean.
* @param handler either a bean name or an actual handler instance
* @see #getMappingForMethod
*/
//找handler bean中的handler methods
protected void detectHandlerMethods(Object handler) {
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
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.isTraceEnabled()) {
logger.trace(formatMappings(userType, methods));
}
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
//核心是这个,注册HandlerMethod到mapping中
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
getHandlerMethods()
获取已经注册的Handler,你会发现HandlerMethod
/**
* Return a (read-only) map with all mappings and HandlerMethod's.
*/
public Map<T, HandlerMethod> getHandlerMethods() {
this.mappingRegistry.acquireReadLock();
try {
return Collections.unmodifiableMap(this.mappingRegistry.getMappings());
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
找到RequestMappingHandlerMapping的两个register方法,看看他注册了什么:
registerMapping(RequestMappingInfo mapping, Object handler, Method method)
registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping)
你会发现两个register方法主要是调用父类的register方法,并且跟新RequestMappingInfo中的ConsumesCondition,
//一个RequestMappingInfo对象(点开会发现各种XXXRequestCondition)
//一个handler
//一个method,调用的方法
@Override
public void registerMapping(RequestMappingInfo mapping, Object handler, Method method) {
//注册,最终会注册到this.mappingRegistry中
super.registerMapping(mapping, handler, method);
//updateConsumesCondition主要是将method中形参列表加到RequestMappingInfo中的ConsumesCondition
updateConsumesCondition(mapping, method);
}
@Override
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
super.registerHandlerMethod(handler, method, mapping);
updateConsumesCondition(mapping, method);
}
AbstractHandlerMapping
AbstractHandlerMapping是AbstractHandlerMethodMapping父类。
AbstractHandlerMapping提供了getHandler(HttpServletRequest request)用于获取HandlerExecutionChain(Handler)
,所以RequestMappingHandlerMapping最终获取的HandlerExecutionChain来自AbstractHandlerMapping提供的getHandler(HttpServletRequest request)
/**
* Look up a handler for the given request, falling back to the default
* handler if no specific one is found.
* @param request current HTTP request
* @return the corresponding handler instance, or the default handler
* @see #getHandlerInternal
*/
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (logger.isTraceEnabled()) {
logger.trace("Mapped to " + handler);
}
else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
logger.debug("Mapped to " + executionChain.getHandler());
}
if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
config = (config != null ? config.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}