精尽Spring MVC源码分析 - HandlerAdapter 组件(三)之 HandlerMethodArgumentResolver (2)

org.springframework.web.method.support.HandlerMethodArgumentResolverComposite,实现 HandlerMethodArgumentResolver 接口,复合的 HandlerMethodArgumentResolver 实现类

构造方法 public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver { /** * HandlerMethodArgumentResolver 数组 */ private final List<HandlerMethodArgumentResolver> argumentResolvers = new LinkedList<>(); /** * MethodParameter 与 HandlerMethodArgumentResolver 的映射,作为缓存 */ private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache = new ConcurrentHashMap<>(256); }

argumentResolvers:HandlerMethodArgumentResolver 数组。这就是 Composite 复合~

argumentResolverCache:MethodParameter 与 HandlerMethodArgumentResolver 的映射,作为缓存。因为,MethodParameter 是需要从 argumentResolvers 遍历到适合其的解析器,通过缓存后,无需再次重复遍历

《HandlerAdapter 组件(一)之 HandlerAdapter》RequestMappingHandlerAdapter小节的 getDefaultArgumentResolvers 方法中可以看到,默认的 argumentResolvers 有哪些 HandlerMethodArgumentResolver 实现类,注意这里是有顺序的添加哦

getArgumentResolver

getArgumentResolver(MethodParameter parameter) 方法,获得方法参数对应的 HandlerMethodArgumentResolver 对象,方法如下:

@Nullable private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) { // 优先从 argumentResolverCache 缓存中,获得 parameter 对应的 HandlerMethodArgumentResolver 对象 HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter); if (result == null) { // 获得不到,则遍历 argumentResolvers 数组,逐个判断是否支持。 for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) { // 如果支持,则添加到 argumentResolverCache 缓存中,并返回 if (resolver.supportsParameter(parameter)) { result = resolver; this.argumentResolverCache.put(parameter, result); break; } } } return result; }

很简单,先从argumentResolverCache缓存中获取,没有获取到则遍历 argumentResolvers,如果支持该参数则该 HandlerMethodArgumentResolver 对象并缓存起来

注意,往 argumentResolvers 添加的顺序靠前,则优先判断是否支持该参数哦~

supportsParameter

实现 supportsParameter(MethodParameter parameter) 方法,如果能获得到对应的 HandlerMethodArgumentResolver 参数处理器,则说明支持处理该参数,方法如下:

@Override public boolean supportsParameter(MethodParameter parameter) { return getArgumentResolver(parameter) != null; } resolveArgument

实现 resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) 方法,解析出指定参数的值,方法如下:

@Override @Nullable public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { // 获取参数解析器 HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); if (resolver == null) { throw new IllegalArgumentException("Unsupported parameter type [" + parameter.getParameterType().getName() + "]. supportsParameter should be called first."); } /** * 进行解析 * * 基于 @RequestParam 注解 * {@link org.springframework.web.method.annotation.RequestParamMethodArgumentResolver#resolveArgument} * 基于 @PathVariable 注解 * {@link org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver#resolveArgument} */ return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory); }

很简单,获取到该方法参数对应的 HandlerMethodArgumentResolver 参数处理器,然后调用其 resolveArgument 执行解析

AbstractNamedValueMethodArgumentResolver

org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver,实现 ValueMethodArgumentResolver 接口,基于名字获取值的HandlerMethodArgumentResolver 抽象基类。例如说,@RequestParam(value = "username") 注解的参数,就是从请求中获得 username 对应的参数值。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwgzpf.html