//通过后置处理器来寻找所有的controller
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#afterPropertiesSet
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#afterPropertiesSet
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#initHandlerMethods
protected void initHandlerMethods() { 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); } } if (beanType != null && isHandler(beanType)) { detectHandlerMethods(beanName); } }
注意下面这段核心代码:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#detectHandlerMethods
通过lambda表达式遍历所有bean中的method,然后遍历method上是否有RequestMapping注解,要注意lambda的使用方法,同时注意里面的细节:包括父类的遍历,factorybean的遍历,最后把controller上的url和method的url合并
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); registerHandlerMethod(handler, invocableMethod, mapping); }); } }
protected void registerHandlerMethod(Object handler, Method method, T mapping) { this.mappingRegistry.register(mapping, handler, method); }
遍历方法的过程
org.springframework.util.ReflectionUtils#doWithMethods(java.lang.Class<?>, org.springframework.util.ReflectionUtils.MethodCallback, org.springframework.util.ReflectionUtils.MethodFilter)
判断是否有@RequestMapping的过程
总结:从spring容器中获取所有bean,然后判断bean是否带有@Controller或者@RequestMapping注解,然后遍历bean中所有的方法,判断方法上是否有@RequestMapping注解,有的话则将其注入到mappingRegistry容器中
其中关系为:mapping为url;handler为bean;method为方法