HandlerMapping继承关系图:
1.BeanNameUrlHandlerMapping
配置文件中配置controller的bean,且bean的id必须以“/”开头,id就是controller可以处理的url
<bean id = "/hello" class="com.liyao.controller.HelloController"/>
2.SimpleUrlHandlerMapping
需要在配置文件中配置controller的bean以及mapping:
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hi">hi</prop>
</props>
</property>
</bean>
<bean id = "hi" class="com.lic.controller.HiController"/>
3.RequestMappingUrlHandlerMapping
基于@RequestMapping注解对应映射
AbstractUrlHandlerMapping 映射器映射出来的是 handler 是 Controller 对象, 也就是类级别的处理器
AbstractHandlerMethodMapping 映射器映射出来的 handler 是 HandlerMethod 对象, 也就是方法级别的处理器
DispatcherServlet#getHandler()方法实现:
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
//遍历所有HandlerMapping, 获取适合当前请求的映射处理器
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
/**
* 1.遍历所有的HandlerMapping,根据Request获取到合适的HandlerMapping
* 2.利用HandlerMapping通过请求信息获取Handler处理器并包装为HandlerExecutionChain执行链
*
* {@link AbstractHandlerMapping#getHandler(HttpServletRequest)}
* hm ==> RequestMappingInfoHandlerMapping
*/
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
分析:
- 遍历所有的注册HandlerMapping,根据Request获取到合适的HandlerMapping
- 利用HandlerMapping通过请求信息获取Handler处理器并包装为HandlerExecutionChain执行链返回
AbstractHandlerMapping#getHandler()方法实现:
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
/**
* 由子类实现, 根据请求信息获取指定的Handler
* {@link AbstractHandlerMethodMapping#getHandlerInternal(HttpServletRequest)}
* {@link AbstractUrlHandlerMapping#getHandlerInternal(javax.servlet.http.HttpServletRequest)}
*/
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
handler = obtainApplicationContext().getBean(handlerName);
}
/**
* 将handler和request包装为HandlerExecutionChain,在HandlerExecutionChain设置了相关过滤器
*/
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
分析:
- 在AbstractHandlerMapping子类中根据请求信息获取指定的Handler
- 如果获取的handler是一个String类型的名称, 则从容器中获取handler实例
- 将handler和request包装为HandlerExecutionChain,在HandlerExecutionChain设置了相关过滤器
1. AbstractHandlerMapping子类一: AbstractHandlerMethodMapping
AbstractHandlerMethodMapping#getHandlerInternal()方法实现:
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
//lookupPath为请求路径信息
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
if (logger.isDebugEnabled()) {
logger.debug("Looking up handler method for path " + lookupPath);
}
this.mappingRegistry.acquireReadLock(); //获取读锁
try {
/**
* 1. 获取HandlerMethod实例(不健全, 数据没有封装完成)
*/
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 + "]");
}
}
/**
* 2. 重塑HandlerMethod实例 ==> 重点
*/
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
分析:
- 根据请求信息获取HandlerMethod实例
- 封装HandlerMethod实例
(1). AbstractHandlerMethodMapping#lookupHandlerMethod()方法实现:
@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
/**
* 由映射处理器映射出对应的MappingInfo信息, 可能获取多个
*/
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
/**
* 将HandlerMethod实例与Request进行包装, 添加到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()) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
//对所有符合条件的处理器进行排序
matches.sort(comparator);
if (logger.isTraceEnabled()) {
logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches);
}
/**
* 获取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.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
/**
* {@link RequestMappingInfoHandlerMapping#handleMatch(org.springframework.web.servlet.mvc.method.RequestMappingInfo, String, HttpServletRequest)}
*/
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
分析:
- 根据url从注册中心获取对应的MappingInfo信息,封装到directPathMatches集合中
- 将HandlerMethod实例与Request进行包装, 并且创建Match实例, 在该实例中封装了HandlerMethod方法
- 由映射处理器(RequestMappingInfoHandlerMapping) 映射出对应的handler
AbstractHandlerMethodMapping#addMatchingMappings()方法实现:
private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
for (T mapping : mappings) {
T match = getMatchingMapping(mapping, request);
if (match != null) {
/**
* 根据请求路径从mappingLookup集合中获取处理方法, 将Method封装到Match实例中
* 后面处理请求时会利用反射执行该方法
*/
matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
}
}
}
(2) HandlerMethod#createWithResolvedBean()方法实现:
public HandlerMethod createWithResolvedBean() {
Object handler = this.bean;
if (this.bean instanceof String) { //如果bean不是实例而是一个BeanName,则从工厂中获取该bean实例
Assert.state(this.beanFactory != null, "Cannot resolve bean name without BeanFactory");
String beanName = (String) this.bean;
// 从工厂中获取bean
handler = this.beanFactory.getBean(beanName);
}
/**
* 问题: 这里为什么要重新创建一个HandlerMethod实例,而不是在原有的HandlerMethod实例上进行修改?
*/
return new HandlerMethod(this, handler);
}
private HandlerMethod(HandlerMethod handlerMethod, Object handler) {
Assert.notNull(handlerMethod, "HandlerMethod is required");
Assert.notNull(handler, "Handler object is required");
this.bean = handler; //反射执行Method时需要传入实例对象
this.beanFactory = handlerMethod.beanFactory;
this.beanType = handlerMethod.beanType;
this.method = handlerMethod.method;
this.bridgedMethod = handlerMethod.bridgedMethod;
this.parameters = handlerMethod.parameters;
this.responseStatus = handlerMethod.responseStatus;
this.responseStatusReason = handlerMethod.responseStatusReason;
this.resolvedFromHandlerMethod = handlerMethod;
}
这里有一个疑问: 为什么要重新创建一个HandlerMethod实例,而不是在原有的HandlerMethod实例上进行修改?
1.1 AbstractHandlerMethodMapping子类: RequestMappingInfoHandlerMapping
在容器初始化过程中创建映射器(RequestMappingHandlerMapping)对象时,会寻找所有被@Controller 注解类中被 @RequestMapping 注解的方法,然后解析方法上的 @RequestMapping 注解,把解析结果封装成 RequestMappingInfo 对象,也就是说RequestMappingInfo 对象是用来装载方法的匹配相关信息,每个匹配的方法都会对应一个 RequestMappingInfo 对象
RequestMappingInfoHandlerMapping#handleMatch()方法实现:
@Override
protected void handleMatch(RequestMappingInfo info, String lookupPath, HttpServletRequest request) {
super.handleMatch(info, lookupPath, request);
String bestPattern;
Map<String, String> uriVariables;
Set<String> patterns = info.getPatternsCondition().getPatterns();
if (patterns.isEmpty()) {
bestPattern = lookupPath;
uriVariables = Collections.emptyMap();
}
else {
bestPattern = patterns.iterator().next();
uriVariables = getPathMatcher().extractUriTemplateVariables(bestPattern, lookupPath);
}
request.setAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE, bestPattern);
if (isMatrixVariableContentAvailable()) {
Map<String, MultiValueMap<String, String>> matrixVars = extractMatrixVariables(request, uriVariables);
request.setAttribute(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE, matrixVars);
}
Map<String, String> decodedUriVariables = getUrlPathHelper().decodePathVariables(request, uriVariables);
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, decodedUriVariables);
if (!info.getProducesCondition().getProducibleMediaTypes().isEmpty()) {
Set<MediaType> mediaTypes = info.getProducesCondition().getProducibleMediaTypes();
request.setAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE, mediaTypes);
}
}
MappingRegistry#getMappingsByUrl()方法实现:
@Nullable
public List<T> getMappingsByUrl(String urlPath) {
return this.urlLookup.get(urlPath);
}
由此可知, 在初始化SpringMVC时处理器已经注册到urlLookup集合中, key为url, 在MappingRegistry#register()方法中实现了对处理器的注册
AbstractHandlerMethodMapping.MappingRegistry#register()方法实现
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
assertUniqueMethodMapping(handlerMethod, mapping);
/**
* mappingLookup: 维护请求信息(RequestMappingInfo)与HandlerMethod的映射关系
*/
this.mappingLookup.put(mapping, handlerMethod);
if (logger.isInfoEnabled()) {
logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod);
}
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
/**
* urlLookup: 维护url与请求信息(RequestMappingInfo)的映射关系
* 后面会根据Url找RequestMappingInfo, 再根据RequestMappingInfo找HandlerMethod对请求进行处理
*/
this.urlLookup.add(url, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
在this.urlLookup.add(url, mapping) 处添加断点查看调用栈:
分析:
- 模块1主要逻辑为创建以及配置Web应用上下文(WebApplicationContext)
- 模块2主要逻辑为springMVC相关bean对象注册解析, 即WebApplicationContext的实例化
- 模块3主要逻辑为遍历所有Controller类, 对类中定义的所有处理方法进行注册,即注册Handler处理器
模块3逻辑分析:
RequestMappingInfoHandlerMapping类实现了InitializingBean接口并重写了afterPropertiesSet(), 在调用初始化方法时, 会触发afterPropertiesSet()方法, 将启动对处理器(handler)的探测以及注册
AbstractHandlerMethodMapping#afterPropertiesSet()方法实现:
@Override
public void afterPropertiesSet() {
//初始化Handler方法, 就是对编写的Control层方法进行注册, key为方法的访问路径, value为对方法的包装类HandlerMethod
initHandlerMethods();
}
protected void initHandlerMethods() {
if (logger.isDebugEnabled()) {
logger.debug("Looking for request mappings in application context: " + getApplicationContext());
}
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 {
//获取对应bean的Class
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()方法用来判断是否符合注册条件, 具体的判断逻辑由子类实现
*/
if (beanType != null && isHandler(beanType)) {
//对Controller类中所有的方法进行探测
detectHandlerMethods(beanName);
}
}
}
handlerMethodsInitialized(getHandlerMethods());
}
AbstractHandlerMethodMapping#detectHandlerMethods()方法实现:
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.isDebugEnabled()) {
logger.debug(methods.size() + " request handler methods found on " + userType + ": " + methods);
}
methods.forEach((method, mapping) -> {
/**
* 循环遍历所有的方法,进行注册
* handler为controller类实例, 每一个HandlerMethod中都维护着该实例, 因为在后面执行该方法时需要传入该实例
*/
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
2.AbstractHandlerMapping子类二: AbstractUrlHandlerMapping
AbstractUrlHandlerMapping#getHandlerInternal()方法实现:
@Override
@Nullable
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
//获取请求路径
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
/**
* 根据请求路径获取handler
*/
Object handler = lookupHandler(lookupPath, request);
if (handler == null) {
// We need to care for the default handler directly, since we need to
// expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.
Object rawHandler = null;
if ("/".equals(lookupPath)) {
rawHandler = getRootHandler();
}
if (rawHandler == null) {
rawHandler = getDefaultHandler();
}
if (rawHandler != null) {
// Bean name or resolved handler?
if (rawHandler instanceof String) {
String handlerName = (String) rawHandler;
rawHandler = obtainApplicationContext().getBean(handlerName);
}
validateHandler(rawHandler, request);
handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
}
}
if (handler != null && logger.isDebugEnabled()) {
logger.debug("Mapping [" + lookupPath + "] to " + handler);
}
else if (handler == null && logger.isTraceEnabled()) {
logger.trace("No handler mapping found for [" + lookupPath + "]");
}
return handler;
}
AbstractUrlHandlerMapping#lookupHandler()方法实现:
@Nullable
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
//尝试直接匹配
Object handler = this.handlerMap.get(urlPath);
if (handler != null) {
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
validateHandler(handler, request);
return buildPathExposingHandler(handler, urlPath, urlPath, null);
}
//尝试模式匹配
List<String> matchingPatterns = new ArrayList<>();
for (String registeredPattern : this.handlerMap.keySet()) {
if (getPathMatcher().match(registeredPattern, urlPath)) {
matchingPatterns.add(registeredPattern);
}
else if (useTrailingSlashMatch()) {
if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", urlPath)) {
matchingPatterns.add(registeredPattern + "/");
}
}
}
String bestMatch = null;
Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);
if (!matchingPatterns.isEmpty()) {
matchingPatterns.sort(patternComparator);
if (logger.isDebugEnabled()) {
logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
}
bestMatch = matchingPatterns.get(0);
}
if (bestMatch != null) {
handler = this.handlerMap.get(bestMatch);
if (handler == null) {
if (bestMatch.endsWith("/")) {
handler = this.handlerMap.get(bestMatch.substring(0, bestMatch.length() - 1));
}
if (handler == null) {
throw new IllegalStateException(
"Could not find handler for best pattern match [" + bestMatch + "]");
}
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
validateHandler(handler, request);
String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestMatch, urlPath);
// There might be multiple 'best patterns', let's make sure we have the correct URI template variables
// for all of them
Map<String, String> uriTemplateVariables = new LinkedHashMap<>();
for (String matchingPattern : matchingPatterns) {
if (patternComparator.compare(bestMatch, matchingPattern) == 0) {
Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars);
uriTemplateVariables.putAll(decodedVars);
}
}
if (logger.isDebugEnabled()) {
logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
}
return buildPathExposingHandler(handler, bestMatch, pathWithinMapping, uriTemplateVariables);
}
// No handler found...
return null;
}
在上面方法中都是通过handlerMap获取指定handler, 那么接下来就看下怎么将handler对象加入handlerMap集合中
AbstractUrlHandlerMapping#registerHandler()方法实现:
protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
Assert.notNull(urlPath, "URL path must not be null");
Assert.notNull(handler, "Handler object must not be null");
Object resolvedHandler = handler;
// Eagerly resolve handler if referencing singleton via name.
if (!this.lazyInitHandlers && handler instanceof String) {
String handlerName = (String) handler;
ApplicationContext applicationContext = obtainApplicationContext();
if (applicationContext.isSingleton(handlerName)) {
resolvedHandler = applicationContext.getBean(handlerName);
}
}
Object mappedHandler = this.handlerMap.get(urlPath);
if (mappedHandler != null) {
if (mappedHandler != resolvedHandler) {
throw new IllegalStateException(
"Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
"]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
}
}
else {
if (urlPath.equals("/")) {
if (logger.isInfoEnabled()) {
logger.info("Root mapping to " + getHandlerDescription(handler));
}
setRootHandler(resolvedHandler);
}
else if (urlPath.equals("/*")) {
if (logger.isInfoEnabled()) {
logger.info("Default mapping to " + getHandlerDescription(handler));
}
setDefaultHandler(resolvedHandler);
}
else {
/**
* 此处完成了对Handler的注册
*/
this.handlerMap.put(urlPath, resolvedHandler);
if (logger.isInfoEnabled()) {
logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));
}
}
}
}
在AbstractUrlHandlerMapping#registerHandler()方法中完成了对handler的注册
查看该方法的调用栈:
通过调用栈可知, 是在子类中调用父类AbstractUrlHandlerMapping的registerHandler()方法
2.1 AbstractUrlHandlerMapping子类一: SimpleUrlHandlerMapping
SimpleUrlHandlerMapping#registerHandlers()方法实现:
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(url, handler);
});
}
}
在SimpleUrlHandlerMapping#registerHandlers(Map<String, Object> urlMap)中调用了SimpleUrlHandlerMapping#registerHandlers(
String urlPath, Object handler)方法
SimpleUrlHandlerMapping#initApplicationContext()方法实现:
@Override
public void initApplicationContext() throws BeansException {
/**
* 其顶级父类AbstractHandlerMapping继承了WebApplicationObjectSupport,容器初始化时会自动调用模板方法
* initApplicationContext, 这里子类重写该方法并加了一些逻辑, 主要是为了将匹配该映射器的Handler对象加入
* 到handlerMap集合中
*/
super.initApplicationContext();
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(url, handler);
});
}
}
2.2 AbstractUrlHandlerMapping子类二: BeanNameUrlHandlerMapping
BeanNameUrlHandlerMapping中没有registerHandlers()方法, 而是由其父类AbstractUrlHandlerMapping进行实现
AbstractDetectingUrlHandlerMapping#initApplicationContext()方法实现:
@Override
public void initApplicationContext() throws ApplicationContextException {
/**
* 其顶级父类AbstractHandlerMapping继承了WebApplicationObjectSupport,容器初始化时会自动调用模板方法
* initApplicationContext, 这里子类重写该方法并加了一些逻辑, 主要是为了将匹配该映射器的Handler对象加入
* 到handlerMap集合中
*/
super.initApplicationContext();
detectHandlers();
}
protected void detectHandlers() throws BeansException {
ApplicationContext applicationContext = obtainApplicationContext();
if (logger.isDebugEnabled()) {
logger.debug("Looking for URL mappings in application context: " + applicationContext);
}
/**
* 将SpringMVC容器中注册的Bean的name都找出来放进数组中
*/
String[] beanNames = (this.detectHandlersInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) :
applicationContext.getBeanNamesForType(Object.class));
// Take any bean name that we can determine URLs for.
for (String beanName : beanNames) {
/**
* 匹配到符合该映射器的bean的name
*/
String[] urls = determineUrlsForHandler(beanName);
if (!ObjectUtils.isEmpty(urls)) {
/**
* 调用父类(AbstractUrlHandlerMapping)的registerHandler方法将匹配的beanName和urls分别作为key和value
* 装进handlerMap集合中
*/
registerHandler(urls, beanName);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Rejected bean name '" + beanName + "': no URL paths identified");
}
}
}
}
BeanNameUrlHandlerMapping#determineUrlsForHandler方法实现:
@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);
}
至此, 处理器的获取解析完成;
相关文章:
SpringMVC源码解析一(在Spring源码项目中搭建SpringMVC源码模块)
SpringMVC源码解析三(处理映射器HandlerMapping的解析)
SpringMVC源码解析四(处理适配器HandlerAdapter的解析)
SpringMVC源码解析五(HandlerMethod执行过程解析)