//通过后置处理器来寻找所有的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为方法
这篇博客深入解析了Spring MVC框架如何通过后置处理器查找并处理带有@Controller和@RequestMapping注解的bean。它详细介绍了AbstractHandlerMethodMapping类的角色,如何遍历bean及其方法,检查RequestMapping注解,并将URL映射注册到mappingRegistry。整个过程涉及到bean的类型检查、方法遍历以及异常处理。
1949

被折叠的 条评论
为什么被折叠?



