本文依旧是对该文件的补充说明:
详解SpringMVC请求的时候是如何找到正确的Controller
处理的封装
自己编写的Controller是如何变成springmvc中的处理器的呢?
在初始化组件的时候。initHandlerMappings(context);是初始化组件名为处理器映射器。顾名思义,就是将处理器和处理器的一些信息映射起来。当请求来的时候,比较信息找到对应的处理器。
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
实际上在使用<mvc:annotation-driven/>
时,解析该标签的时候,springmvc就已经将组件实例化到容器中了。org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
这个类实现了InitializingBean
接口,所以关注下afterPropertiesSet()
方法,看下实例化完成后,做什么什么工作。
直接进入到方法
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#initHandlerMethods
protected void initHandlerMethods() {
// 得到所有的Object的bean名称
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
processCandidateBean(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
protected void processCandidateBean(String beanName) {
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.isTraceEnabled()) {
logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
}
}
// RequestMappingHandlerMapping重写了该方法,类有@Controller注解或者有@RequestMapping注解
if (beanType != null && isHandler(beanType)) {
// 如果该类符合,就从该类找找处理器方法。
detectHandlerMethods(beanName);
}
}
protected void detectHandlerMethods(Object handler) {
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
Class<?> userType = ClassUtils.getUserClass(handlerType);
// 遍历这个类的所有方法,根据条件,筛选出所有符合的方法。
// 这个方法用@RequestMapping注解注释,并从中解析出RequestMappingInfo
// T 就是RequestMappingInfo
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> {
try {
return getMappingForMethod(method, userType);
}
catch (Throwable ex)