RequestMappingHandlerMapping 初始化

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) {
    }
...
}
复制代码
  1. 加载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>

  1. 加载RequestMappingHandlerMapping
    作为RequestMappingInfoHandlerMapping的子类,RequestMappingHandlerMapping也被加载到了。

在加载RequestMappingHandlerMappingde时候,按照上图显示会执行 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做了实现

  1. 注册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();
	}
}
复制代码

注册的过程,大致就是对mappingLookupurlLookupcorsLookup完成注册 这三个结构内容如下

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)
复制代码

转载于:https://juejin.im/post/5d14cfd4f265da1bd3056c32

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值