RequestMappingHandlerMapping 初始化
graph TD
1(spring环境启动,加载DocumentationPluginsBootstrapper)-->2(加载接口RequestHandlerProvider的实现类bean)
2-->3(加载RequestMappingInfoHandlerMapping的实现类的bean)
3-->4(这个时候我们的RequestMappingHandlerMapping就会被加在了)
复制代码
代码内容:
1.加载 DocumentationPluginsBootstrapper
在spring的环境启动的时候,DocumentationPluginsBootstrapper就会被加载,这个时候,作为构造函数中的参数List也会被依赖加载
@Component
public class DocumentationPluginsBootstrapper implements SmartLifecycle {
...
@Autowired
public DocumentationPluginsBootstrapper(DocumentationPluginsManager documentationPluginsManager, List<RequestHandlerProvider> handlerProviders, DocumentationCache scanned, ApiDocumentationScanner resourceListing, TypeResolver typeResolver, Defaults defaults, ServletContext servletContext) {
}
...
}
复制代码
- 加载
WebMvcRequestHandlerProvider
加载List的时候,会去加载实现了RequestHandlerProvider接口的bean,查看了源代码,只有WebMvcRequestHandlerProvider一个实现类,好像
@Component
@Order(-2147483648)
public class WebMvcRequestHandlerProvider implements RequestHandlerProvider {
private final List<RequestMappingInfoHandlerMapping> handlerMappings;
private final HandlerMethodResolver methodResolver;
@Autowired
public WebMvcRequestHandlerProvider(HandlerMethodResolver methodResolver, List<RequestMappingInfoHandlerMapping> handlerMappings) {
this.handlerMappings = handlerMappings;
this.methodResolver = methodResolver;
}
}
复制代码
加载WebMvcRequestHandlerProvider的时候,又会去加载List<RequestMappingInfoHandlerMapping>
- 加载
RequestMappingHandlerMapping
作为RequestMappingInfoHandlerMapping的子类,RequestMappingHandlerMapping也被加载到了。
initHandlerMethods
,其中就会完成对HandlerMethod的注册
/**
* Look for handler methods in a handler.
* @param handler the bean name of a handler or a handler instance
*/
protected void detectHandlerMethods(final Object handler) {
Class<?> handlerType = (handler instanceof String ?
getApplicationContext().getType((String) handler) : handler.getClass());
final Class<?> userType = ClassUtils.getUserClass(handlerType);
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
new MethodIntrospector.MetadataLookup<T>() {
@Override
public T inspect(Method 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);
}
for (Map.Entry<Method, T> entry : methods.entrySet()) {
Method invocableMethod = AopUtils.selectInvocableMethod(entry.getKey(), userType);
T mapping = entry.getValue();
registerHandlerMethod(handler, invocableMethod, mapping);
}
}
复制代码
上面的代码,遍历当前bean的所有方法,封装成RequestMappingInfo,并完成注册
封装的RequestMappingInfo的方法getMappingForMethod
在RequestMappingHandlerMapping做了实现
- 注册
HandlerMethod
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}
复制代码
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
assertUniqueMethodMapping(handlerMethod, mapping);
if (logger.isInfoEnabled()) {
logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod);
}
this.mappingLookup.put(mapping, handlerMethod);
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
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<T>(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
复制代码
注册的过程,大致就是对mappingLookup
、urlLookup
、corsLookup
完成注册 这三个结构内容如下
private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<T, HandlerMethod>();
private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<String, T>();
private final Map<HandlerMethod, CorsConfiguration> corsLookup =
new ConcurrentHashMap<HandlerMethod, CorsConfiguration>();
复制代码
这三个结构的内容,会为后续的请求匹配对应的处理HandlerMethod
提供判断依据
完成上述步骤,能看到下面的日志打出,标识我们的请求连接已经可以和处理逻辑的HandlerMethod关联上了
2019-06-27 22:42:48 752 [restartedMain] [] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/api/manager/v1/organization/level/list],methods=[GET]}" onto public java.util.List<java.lang.Integer> com.test.controller.manager.OrganizationController.getOrgLevelList(java.lang.Integer)
复制代码