graph TD
1(spring環境啓動,加載DocumentationPluginsBootstrapper)-->2(加載接口RequestHandlerProvider的實現類bean)
2-->3(加載RequestMappingInfoHandlerMapping的實現類的bean)
3-->4(這個時候咱們的RequestMappingHandlerMapping就會被加在了)
複製代碼
代碼內容:java
1.加載 DocumentationPluginsBootstrapper
在spring的環境啓動的時候,DocumentationPluginsBootstrapper就會被加載,這個時候,做爲構造函數中的參數List也會被依賴加載spring
@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
@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>
api
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,並完成註冊bash
封裝的RequestMappingInfo的方法getMappingForMethod
在RequestMappingHandlerMapping作了實現app
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
完成註冊 這三個結構內容以下cors
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
提供判斷依據ide
完成上述步驟,能看到下面的日誌打出,標識咱們的請求鏈接已經能夠和處理邏輯的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)
複製代碼