Spring MVC之RequestMappingHandlerAdapter初始化
RequestMappingHandlerAdapter基于注解的处理器适配器,目的是用来执行handler,同时返回modelAndView给前端控制器,这块个人感觉是spring mvc的核心了,所以我会详细一些记录。
本篇文章先记录他初始化都做了什么。
先上类图:
通过类图可以看到,实现了InitializingBean接口,所以入口的方法就是 afterPropertiesSet();
下面来看代码:
1 public void afterPropertiesSet() {
2 List handlers;
3 if (this.argumentResolvers == null) { //加载默认的参数解析器
4 handlers = this.getDefaultArgumentResolvers();
5 this.argumentResolvers = (new HandlerMethodArgumentResolverComposite()).addResolvers(handlers);
6 }
7
8 if (this.initBinderArgumentResolvers == null) { //加载@initBinder注解的解析器
9 handlers = this.getDefaultInitBinderArgumentResolvers();
10 this.initBinderArgumentResolvers = (new HandlerMethodArgumentResolverComposite()).addResolvers(handlers);
11 }
12
13 if (this.returnValueHandlers == null) { //加载默认返回值的解析器
14 handlers = this.getDefaultReturnValueHandlers();
15 this.returnValueHandlers = (new HandlerMethodReturnValueHandlerComposite()).addHandlers(handlers);
16 }
17
18 this.initControllerAdviceCache(); //缓存 类有@ControllerAdvice 且@ModelAttribute 和 @InitBinder的注解的方法
19 }
注意:这些解析器实际上都是一个*****Composite结尾的包装类,实际上就是责任链模式的管理类,提供查找具体的解析器和执行方法,这块内容就不多描述了.
就拿参数解析器为例:
1 private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
2 List<HandlerMethodArgumentResolver> resolvers = new ArrayList();
3 resolvers.add(new RequestParamMethodArgumentResolver(this.getBeanFactory(), false));
4 resolvers.add(new RequestParamMapMethodArgumentResolver());
5 resolvers.add(new PathVariableMethodArgumentResolver());
6 resolvers.add(new PathVariableMapMethodArgumentResolver());
7 resolvers.add(new MatrixVariableMethodArgumentResolver());
8 resolvers.add(new MatrixVariableMapMethodArgumentResolver());
9 resolvers.add(new ServletModelAttributeMethodProcessor(false)); //没有注解的pojo对象参数 使用它解析的
//@ResponseBody注解用的,实际上输入和输出都有他,他实现了俩接口
10 resolvers.add(new RequestResponseBodyMethodProcessor(this.getMessageConverters()));
11 resolvers.add(new RequestPartMethodArgumentResolver(this.getMessageConverters()));
12 resolvers.add(new RequestHeaderMethodArgumentResolver(this.getBeanFactory()));
13 resolvers.add(new RequestHeaderMapMethodArgumentResolver());
14 resolvers.add(new ServletCookieValueMethodArgumentResolver(this.getBeanFactory()));
15 resolvers.add(new ExpressionValueMethodArgumentResolver(this.getBeanFactory()));
16 resolvers.add(new ServletRequestMethodArgumentResolver());
17 resolvers.add(new ServletResponseMethodArgumentResolver());
18 resolvers.add(new HttpEntityMethodProcessor(this.getMessageConverters()));
19 resolvers.add(new RedirectAttributesMethodArgumentResolver());
20 resolvers.add(new ModelMethodProcessor());
21 resolvers.add(new MapMethodProcessor());
22 resolvers.add(new ErrorsMethodArgumentResolver());
23 resolvers.add(new SessionStatusMethodArgumentResolver());
24 resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
25 if (this.getCustomArgumentResolvers() != null) { //自定义的参数解析器
26 resolvers.addAll(this.getCustomArgumentResolvers());
27 }
28
29 resolvers.add(new RequestParamMethodArgumentResolver(this.getBeanFactory(), true)); //据说全能的,有时间看下代码
30 resolvers.add(new ServletModelAttributeMethodProcessor(true));
31 return resolvers;
32 }
下面来看initControllerAdviceCache()方法
1 private void initControllerAdviceCache() {
2 if (this.getApplicationContext() != null) {
3 if (this.logger.isDebugEnabled()) {
4 this.logger.debug("Looking for controller advice: " + this.getApplicationContext());
5 }
6 //获取所有有@ControllerAdvice的Bean
7 List<ControllerAdviceBean> beans = ControllerAdviceBean.findAnnotatedBeans(this.getApplicationContext());
8 Collections.sort(beans, new OrderComparator());
9 Iterator i$ = beans.iterator();
10
11 while(i$.hasNext()) {
12 ControllerAdviceBean bean = (ControllerAdviceBean)i$.next(); //遍历bean拿到@ModelAttribute的方法
13 Set<Method> attrMethods = HandlerMethodSelector.selectMethods(bean.getBeanType(), MODEL_ATTRIBUTE_METHODS);
14 if (!attrMethods.isEmpty()) {
15 this.modelAttributeAdviceCache.put(bean, attrMethods); //缓存起来
16 this.logger.info("Detected @ModelAttribute methods in " + bean);
17 }
18 //拿到有@InitBinder的方法
19 Set<Method> binderMethods = HandlerMethodSelector.selectMethods(bean.getBeanType(), INIT_BINDER_METHODS);
20 if (!binderMethods.isEmpty()) {
21 this.initBinderAdviceCache.put(bean, binderMethods); //缓存起来
22 this.logger.info("Detected @InitBinder methods in " + bean);
23 }
24 }
25
26 }
27 }
到此为止,初始化完成