在理解初始化之前,先来认识一个接口
HandlerMethodArgumentResolver
方法参数解析器接口,这个接口是SpringMVC参数解析绑定的核心接口。不同的参数类型绑定都是通过实现这个接口来实现。也可以通过实现这个接口来自定义参数解析器。这个接口中有如下两个方法
public interface HandlerMethodArgumentResolver {
//该解析器是否支持parameter参数的解析
boolean supportsParameter(MethodParameter parameter);
//将方法参数从给定请求(webRequest)解析为参数值并返回
Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception;
}
初始化
RequestMappingHandlerAdapter.java类的afterPropertiesSet(line:481)方法初始化相关方法参数解析器。代码如下
public void afterPropertiesSet() {
if (this.argumentResolvers == null) {
//初始化
SpringMVC默认的方法参数解析器,并添加至argumentResolvers(HandlerMethodArgumentResolverComposite)
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.initBinderArgumentResolvers == null) {
//初始化SpringMVC默认的初始化绑定器(@InitBinder)参数解析器,并添加至initBinderArgumentResolvers(HandlerMethodArgumentResolverComposite)
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.returnValueHandlers == null) {
//获取默认的方法返回值解析器
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
initControllerAdviceCache();
}
现在我们进入getDefalutArgumentResolvers方法,代码如下
//默认的参数解析,创建了默认的24个参数解析器,并添加至resolvers
//这里的24个参数解析器都是针对不同的参数类型来解析的
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();
// 基于注解的参数解析器
//一般用于带有@RequestParam注解的简单参数绑定,简单参数比如byte、int、long、double、String以及对应的包装类型
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
//用于处理带有@RequestParam注解,且参数类型为Map的解析绑定
resolvers.add(new RequestParamMapMethodArgumentResolver());
//一般用于处理带有@PathVariable注解的默认参数绑定
resolvers.add(new PathVariableMethodArgumentResolver());
//也是用于带有@PathVariable注解的Map相关参数绑定,后续还有一些默认的参数解析器。后续还有一些参数解析器,我这里都不一一解释了。想具体确认某个参数会交个哪个参数解析器处理,可以通过以下解析器的supportsParameter(MethodParameter parameter)方法得知
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters()));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters()));
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
// 基于类型的参数解析器
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters()));
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
resolvers.add(new MapMethodProcessor());
resolvers.add(new ErrorsMethodArgumentResolver());
resolvers.add(new SessionStatusMethodArgumentResolver());
resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
// Custom arguments
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
参数解析器添加至HandlerMethodArgumentResolverComposite这个类,这个也是实现了HandlerMethodArgumentResolver接口。这里运用涉及模式中的composite模式(组合模式),SpringMVC中,所有请求的参数解析都是进入HandlerMethodArgumentResolverComposite类来完成的。它有两个成员变量,如下
//它的元素在RequestMappingHandlerAdapter类的afterPropertiesSet方法中被添加,存放的是SpringMVC一些默认的HandlerMethodArgumentResolver参数解析器
private final List<HandlerMethodArgumentResolver> argumentResolvers =
new LinkedList<HandlerMethodArgumentResolver>();
//存放已经解析过的参数,已经对应的HandlerMethodArgumentResolver解析器。加快查找过程
private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache =
new ConcurrentHashMap<MethodParameter, HandlerMethodArgumentResolver>(256);
介绍了这么多,话不多说。直接来看一个详细解析绑定过程吧
绑定过程