当前位置: 代码迷 >> VC/MFC >> SpringMVC源码小结(二)mvc:annotation
  详细解决方案

SpringMVC源码小结(二)mvc:annotation

热度:146   发布时间:2016-05-02 03:17:34.0
SpringMVC源码总结(二)mvc:annotation

SpringMVC源码总结(二)mvc:annotation

???
?

?

?

?

??

?

?
?
上一篇文章让我们了解HandlerMapping和HandlerAdapter以及默认采取的策略,这篇文章就要讲述mvc:annotation-driven对默认策略的改变。它背后到底注册了哪些HandlerMapping和HandlerAdapter。?

首先可以在DispatcherServlet的initStrategies方法中的initHandlerMappings和initHandlerAdapters中打上断点,来查看注册了哪些HandlerMapping和HandlerAdapter
?

Java代码??收藏代码

  1. protected?void?initStrategies(ApplicationContext?context)?{??

  2. ????????initMultipartResolver(context);??

  3. ????????initLocaleResolver(context);??

  4. ????????initThemeResolver(context);??

  5. ????????initHandlerMappings(context);??

  6. ????????initHandlerAdapters(context);??

  7. ????????initHandlerExceptionResolvers(context);??

  8. ????????initRequestToViewNameTranslator(context);??

  9. ????????initViewResolvers(context);??

  10. ????????initFlashMapManager(context);??

  11. ????}??


目前我的spring版本是4.0.5。我查看的结果:?
HandlerMapping:注册了 RequestMappingHandlerMapping和BeanNameUrlHandlerMapping?
HandlerAdapter:注册了 RequestMappingHandlerAdapter、HttpRequestHandlerAdapter和SimpleControllerHandlerAdapter?
这几个HandlerMapping和HandlerAdapter上文都提到过。?
下面就要查看下具体的注册过程:?
在xml文件中配置mvc:annotation-driven,肯定有一个专门的类来解析处理这个东西。?
会有这样的一个接口BeanDefinitionParser,它只有一个方法:
?

Java代码??收藏代码

  1. public?interface?BeanDefinitionParser?{??

  2. ??

  3. ????/**?

  4. [email protected]}?and?register?the?resulting?

  5. [email protected](s)}?with?the?

  6. [email protected]Context#getRegistry()?BeanDefinitionRegistry}?

  7. [email protected]}.?

  8. ?????*?<p>[email protected]on}?that?results?

  9. ?????*?from?the?parse?if?they?will?ever?be?used?in?a?nested?fashion?(for?example?as?

  10. [email protected]<property/>}?tag).?Implementations?may?return?

  11. [email protected]}?if?they?will?<strong>not</strong>?be?used?in?a?nested?fashion.?

  12. [email protected][email protected] BeanDefinitions}?

  13. [email protected]he?current?state?of?the?parsing?process;?

  14. [email protected].beans.factory.support.BeanDefinitionRegistry}?

  15. [email protected][email protected]}?

  16. ?????*/??

  17. ????BeanDefinition?parse(Element?element,?ParserContext?parserContext);??

  18. ??

  19. }??


它是用来专门处理<beans></beans>里面的配置元素。然后我们会找到这样的一个实现类AnnotationDrivenBeanDefinitionParser,它的文档介绍如下:?

Java代码??收藏代码

  1. /**?

  2. ?*?这里清清楚楚写着该类是专门处理?<mvc:annotation-driven/>标签的?

  3. [email protected]}?that?provides?the?configuration?for?the?

  4. [email protected]<annotation-driven/>}?MVC?namespace??element.?

  5. ?*?

  6. ?*?这里说明了注册的HandlerMapping?

  7. ?*?<p>[email protected]}s:</p>?

  8. ?*?<ul>?

  9. ?*??<li>[email protected]}?

  10. ?*??ordered?at?0?for?mapping?requests?to?annotated?controller?methods.?

  11. ?*??<li>[email protected]}?

  12. ?*??ordered?at?2?to?map?URL?paths?to?controller?bean?names.?

  13. ?*?</ul>?

  14. ?*?

  15. ?*?<p><strong>Note:</strong>?Additional?HandlerMappings?may?be?registered?

  16. [email protected]<view-controller>}?or?the?

  17. [email protected]<resources>}?MVC?namespace?elements.?

  18. ?*?

  19. ?*?这里说明了注册的HandlerAdapter?

  20. ?*?<p>[email protected]}s:?

  21. ?*?<ul>?

  22. ?*??<li>[email protected]}?

  23. ?*??for?processing?requests?with?annotated?controller?methods.?

  24. ?*??<li>[email protected]}?

  25. [email protected]r}s.?

  26. ?*??<li>[email protected]}?

  27. [email protected]Controller}s.?

  28. ?*?</ul>?

  29. ?*?

  30. ?*?<p>[email protected]esolver}s:?

  31. ?*?<ul>?

  32. ?*??<li>[email protected]}?for?handling?exceptions?

  33. ?*??through?@[email protected]}?methods.?

  34. ?*??<li>[email protected]}?for?exceptions?annotated?

  35. ?*??with?@[email protected]}.?

  36. ?*??<li>[email protected]}?for?resolving?known?Spring?

  37. ?*??exception?types?

  38. ?*?</ul>?

  39. ?*?

  40. ?*?<p>[email protected]}?and?the?

  41. [email protected]}?are?configured?with?instances?of?

  42. ?*?the?following?by?default:?

  43. ?*?<ul>?

  44. ?*??<li>[email protected]}?

  45. ?*??<li>[email protected]}?

  46. ?*??<li>[email protected]idatorFactoryBean}?

  47. ?*??if?a?JSR-303?implementation?is?available?on?the?classpath?

  48. ?*??<li>[email protected]}s?depending?on?what?3rd?party?

  49. ?*??libraries?are?available?on?the?classpath.?

  50. ?*?</ul>?

  51. ?*?

  52. [email protected]

  53. [email protected]

  54. [email protected]

  55. [email protected]

  56. [email protected]

  57. [email protected]

  58. ?*/??

  59. class?AnnotationDrivenBeanDefinitionParser?implements?BeanDefinitionParser?{??

  60. ??????????//先省略,请详细看下它的文档介绍??

  61. }??


上面的文档对mvc:annotation-driven注册的东西都有详细的说明。?
具体看解析过程的代码的内容:
?

Java代码??收藏代码

  1. @Override??

  2. ????public?BeanDefinition?parse(Element?element,?ParserContext?parserContext)?{??

  3. ????????Object?source?=?parserContext.extractSource(element);??

  4. ??

  5. ????????//省略??

  6. ????????RootBeanDefinition?handlerMappingDef?=?new?RootBeanDefinition(RequestMappingHandlerMapping.class);??

  7. ??????????

  8. ????????RootBeanDefinition?handlerAdapterDef?=?new?RootBeanDefinition(RequestMappingHandlerAdapter.class);??

  9. ??????????

  10. ????????????//省略,??

  11. ????????//?Ensure?BeanNameUrlHandlerMapping?(SPR-8289)?and?default?HandlerAdapters?are?not "turned?off"??

  12. ????????MvcNamespaceUtils.registerDefaultComponents(parserContext,?source);??

  13. ??

  14. ????????parserContext.popAndRegisterContainingComponent();??

  15. ??

  16. ????????return?null;??

  17. ????}??


MvcNamespaceUtils.registerDefaultComponents的内容如下:?

Java代码??收藏代码

  1. public?static?void?registerDefaultComponents(ParserContext?parserContext,?Object?source)?{??

  2. ????????registerBeanNameUrlHandlerMapping(parserContext,?source);??

  3. ????????registerHttpRequestHandlerAdapter(parserContext,?source);??

  4. ????????registerSimpleControllerHandlerAdapter(parserContext,?source);??

  5. ????}??


至此所注册的HandlerMapping和HandlerAdapter我们都找到了。?
然后我们就可以体验下RequestMappingHandlerMapping和BeanNameUrlHandlerMapping,这两个HandlerMapping。由于上一篇文章已经体验过了BeanNameUrlHandlerMapping,接下来就要体验下RequestMappingHandlerMapping,然后你会发觉又有一系列的新名词走进我们的视野,需要我们去弄清楚。?
先体验下:?

首先还是web.xml的配置:
?

Java代码??收藏代码

  1. <!DOCTYPE?web-app?PUBLIC??

  2. ?"-//Sun?Microsystems,?Inc.//DTD?Web?Application?2.3//EN"??

  3. ?"http://java.sun.com/dtd/web-app_2_3.dtd"?>??

  4. ??

  5. <web-app>??

  6. ??<display-name>Archetype?Created?Web?Application</display-name>??

  7. ??<servlet>??

  8. ????????<servlet-name>mvc</servlet-name>??

  9. ????????<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>??

  10. ????????<load-on-startup>1</load-on-startup>??

  11. ????</servlet>??

  12. ??

  13. ????<servlet-mapping>??

  14. ????????<servlet-name>mvc</servlet-name>??

  15. ????????<url-pattern>/*</url-pattern>??

  16. ????</servlet-mapping>??

  17. </web-app>??


最简单的配置,然后是[servlet-name]-servlet.xml,本工程即mvc-servlet.xml:?

Java代码??收藏代码

  1. <?xml?version="1.0"?encoding="UTF-8"??>??

  2. <beans?xmlns="http://www.springframework.org/schema/beans"?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"?xmlns:mvc="http://www.springframework.org/schema/mvc"?xmlns:util="http://www.springframework.org/schema/util"?xmlns:context="http://www.springframework.org/schema/context"??

  3. ????xsi:schemaLocation="http://www.springframework.org/schema/beans??

  4. ????http://www.springframework.org/schema/beans/spring-beans-3.1.xsd??

  5. ????http://www.springframework.org/schema/mvc??

  6. ????http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd??

  7. ????http://www.springframework.org/schema/util??

  8. ????http://www.springframework.org/schema/util/spring-util-2.0.xsd??

  9. ????http://www.springframework.org/schema/context???

  10. ????http://www.springframework.org/schema/context/spring-context-3.2.xsd">??

  11. ??????

  12. ??????

  13. ????<mvc:annotation-driven/>??

  14. ??????

  15. ????<bean?class="com.lg.mvc.StringAction"/>??

  16. ????<bean?name="/index"?class="com.lg.mvc.HomeAction"></bean>??

  17. ??????

  18. ??????

  19. ????<bean?class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">??

  20. ????????<property?name="templateLoaderPath"?value="/WEB-INF/views"?/>??

  21. ????????<property?name="defaultEncoding"?value="utf-8"?/>??

  22. ????????<property?name="freemarkerSettings">??

  23. ????????????<props>??

  24. ????????????????<prop?key="locale">zh_CN</prop>??

  25. ????????????</props>??

  26. ????????</property>??

  27. ????</bean>??

  28. ????<bean?class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">??

  29. ????????<property?name="suffix"?value=".html"?/>??

  30. ????????<property?name="contentType"?value="text/html;charset=utf-8"?/>??

  31. ????????<property?name="requestContextAttribute"?value="request"?/>??

  32. ????????<property?name="exposeRequestAttributes"?value="true"?/>??

  33. ????????<property?name="exposeSessionAttributes"?value="true"?/>??

  34. ????</bean>??

  35. </beans>??


开启了<mvc:annotation-driven/>,同时注册了两个bean。有RequestMappingHandlerMapping和RequestMappingHandlerAdapter作为后盾支持,[email protected]@[email protected]@RequestMapping无关的,[email protected][email protected]ng也是挺重要的,但不是必须的。这里简单说明下:[email protected][email protected],如果有其一则会将该bean纳入作为它的处理对象,[email protected]?[email protected]?(作为基础地址),也可以配置在方法上,[email protected],有时候又不会,[email protected]@RequestMapping,RequestMappingHandlerMapping都会将他们纳入自己的handler[email protected]?是不被处理的,[email protected]@Controller,[email protected],你可以试验下,稍后会做源代码说明。下面继续,[email protected]@RequestMapping注解的StringAction类?

Java代码??收藏代码

  1. package?com.lg.mvc;??

  2. ??

  3. import?java.io.UnsupportedEncodingException;??

  4. ??

  5. import?org.springframework.stereotype.Controller;??

  6. import?org.springframework.web.bind.annotation.RequestMapping;??

  7. import?org.springframework.web.bind.annotation.RequestMethod;??

  8. import?org.springframework.web.bind.annotation.ResponseBody;??

  9. ??

  10. @Controller??

  11. public?class?StringAction?{??

  12. ??????

  13. [email protected]

  14. [email protected](value="/string",method=RequestMethod.GET)??

  15. ????public?String?testMessageConverter(String?name)?throws?UnsupportedEncodingException{??

  16. ????????System.out.println(name);??

  17. ????????return?name;??

  18. ????}??

  19. }??


然后就可以运行一下,体验一下,先不要管乱码问题,这个问题引出了下一篇文章spring框架中的乱码问题。?
运行结果如下:?

?
证明整个流程跑通了。?
[email protected]ingHandlerMapping管理,RequestMappingHandlerMapping会将这个handler和handler中的每[email protected]ethod对象,该类的构造函数为HandlerMethod(Object bean, Method method),经过这样的包装之后将构造的HandlerMethod对象作为新的handler,然后进行选择适配器,进行方法调用,当RequestMappingHandlerAdapter判断是否support一个类时,就是依据当前的handlelr是否是HandlerMethod类型。若是则由RequestMappingHandlerAdapter来调度执行该handler(handler为HandlerMethod类型)的中的method方法。以上就是整个大体的流程。下面就要用代码来事实说话:?
第一步要弄清RequestMappingHandlerMapping在初始化时是如何寻找它所管辖的bean。说说我找代码的具体流程:?
RequestMappingHandlerMapping的父类AbstractHandlerMethodMapping在初始化时,会调用到这样的一个方法initHandlerMethods,在该方法中,[email protected]?[email protected]
?

Java代码??收藏代码

  1. /**?

  2. ?????*?Scan?beans?in?the?ApplicationContext,?detect?and?register?handler?methods.?

  3. [email protected]#isHandler(Class)?

  4. [email protected]#getMappingForMethod(Method,?Class)?

  5. [email protected]#handlerMethodsInitialized(Map)?

  6. ?????*/??

  7. ????protected?void?initHandlerMethods()?{??

  8. ????????if?(logger.isDebugEnabled())?{??

  9. ????????????logger.debug("Looking?for?request?mappings?in?application?context:?"?+?getApplicationContext());??

  10. ????????}??

  11. ??

  12. ????????String[]?beanNames?=?(this.detectHandlerMethodsInAncestorContexts????

  13. ????????????????BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(),?Object.class)?:??

  14. ????????????????getApplicationContext().getBeanNamesForType(Object.class));??

  15. ??

  16. ????????for?(String?beanName?:?beanNames)?{??

  17. ????????????if?(!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)?&&??

  18. ????????????????????isHandler(getApplicationContext().getType(beanName))){??

  19. ????????????????detectHandlerMethods(beanName);??

  20. ????????????}??

  21. ????????}??

  22. ????????handlerMethodsInitialized(getHandlerMethods());??

  23. ????}??


其中的isHandler的判断方法代码如下:?

Java代码??收藏代码

  1. /**?

  2. [email protected]}?

  3. ?????*?Expects?a?handler?to?have?a?type-level?@[email protected]}?annotation.?

  4. ?????*/??

  5. [email protected]

  6. ????protected?boolean?isHandler(Class<?>?beanType)?{??

  7. ????????return?((AnnotationUtils.findAnnotation(beanType,?Controller.class)?!=?null)?||??

  8. ????????????????(AnnotationUtils.findAnnotation(beanType,?RequestMapping.class)?!=?null));??

  9. ????}??


如果handler含有了上述注解的其中之一,[email protected]??方法:?

Java代码??收藏代码

  1. /**?

  2. ?????*?Look?for?handler?methods?in?a?handler.?

  3. [email protected]?a?handler?instance?

  4. ?????*/??

  5. ????protected?void?detectHandlerMethods(final?Object?handler)?{??

  6. ????????Class<?>?handlerType?=??

  7. ????????????????(handler?instanceof?String???getApplicationContext().getType((String)?handler)?:?handler.getClass());??

  8. ??

  9. ????????//?Avoid?repeated?calls?to?getMappingForMethod?which?would?rebuild?RequestMappingInfo?instances??

  10. ????????final?Map<Method,?T>?mappings?=?new?IdentityHashMap<Method,?T>();??

  11. ????????final?Class<?>?userType?=?ClassUtils.getUserClass(handlerType);??

  12. ??

  13. ????????Set<Method>?methods?=?HandlerMethodSelector.selectMethods(userType,?new?MethodFilter()?{??

  14. [email protected]

  15. ????????????public?boolean?matches(Method?method)?{??

  16. ????????????????T?mapping?=?getMappingForMethod(method,?userType);??

  17. ????????????????if?(mapping?!=?null)?{??

  18. ????????????????????mappings.put(method,?mapping);??

  19. ????????????????????return?true;??

  20. ????????????????}??

  21. ????????????????else?{??

  22. ????????????????????return?false;??

  23. ????????????????}??

  24. ????????????}??

  25. ????????});??

  26. ??

  27. ????????for?(Method?method?:?methods)?{??

  28. ????????????registerHandlerMethod(handler,?method,?mappings.get(method));??

  29. ????????}??

  30. ????}??


遍历这个handler类的所有方法,过滤条件就是这个内部类MethodFilter,其中的getMappingForMethod方法内容为:?

Java代码??收藏代码

  1. /**?

  2. ?????*?Uses?method?and?type-level?@[email protected]}?annotations?to?create?

  3. ?????*?the?RequestMappingInfo.?

  4. [email protected],[email protected]}?if?the?method?

  5. [email protected]@RequestMapping}?annotation.?

  6. [email protected]#getCustomMethodCondition(Method)?

  7. [email protected]#getCustomTypeCondition(Class)?

  8. ?????*/??

  9. [email protected]

  10. ????protected?RequestMappingInfo?getMappingForMethod(Method?method,?Class<?>?handlerType)?{??

  11. ????????RequestMappingInfo?info?=?null;??

  12. ????????RequestMapping?methodAnnotation?=?AnnotationUtils.findAnnotation(method,?RequestMapping.class);??

  13. ????????if?(methodAnnotation?!=?null)?{??

  14. ????????????RequestCondition<?>?methodCondition?=?getCustomMethodCondition(method);??

  15. ????????????info?=?createRequestMappingInfo(methodAnnotation,?methodCondition);??

  16. ????????????RequestMapping?typeAnnotation?=?AnnotationUtils.findAnnotation(handlerType,?RequestMapping.class);??

  17. ????????????if?(typeAnnotation?!=?null)?{??

  18. ????????????????RequestCondition<?>?typeCondition?=?getCustomTypeCondition(handlerType);??

  19. ????????????????info?=?createRequestMappingInfo(typeAnnotation,?typeCondition).combine(info);??

  20. ????????????}??

  21. ????????}??

  22. ????????return?info;??

  23. ????}??


如找到了含有RequestMapping注释的方法,则由这个注释的内容构建一个RequestMappingInfo对象:?

Java代码??收藏代码

  1. /**?

  2. ?????*?Created?a?RequestMappingInfo?from?a?RequestMapping?annotation.?

  3. ?????*/??

  4. ????protected?RequestMappingInfo?createRequestMappingInfo(RequestMapping?annotation,?RequestCondition<?>?customCondition)?{??

  5. ????????String[]?patterns?=?resolveEmbeddedValuesInPatterns(annotation.value());??

  6. ????????return?new?RequestMappingInfo(??

  7. ????????????????new?PatternsRequestCondition(patterns,?getUrlPathHelper(),?getPathMatcher(),??

  8. ????????????????????????this.useSuffixPatternMatch,?this.useTrailingSlashMatch,?this.fileExtensions),??

  9. ????????????????new?RequestMethodsRequestCondition(annotation.method()),??

  10. ????????????????new?ParamsRequestCondition(annotation.params()),??

  11. ????????????????new?HeadersRequestCondition(annotation.headers()),??

  12. ????????????????new?ConsumesRequestCondition(annotation.consumes(),?annotation.headers()),??

  13. ????????????????new?ProducesRequestCondition(annotation.produces(),?annotation.headers(),?this.contentNegotiationManager),??

  14. ????????????????customCondition);??

  15. ????}??


就是拿RequestMapping注释的内容进一步封装进RequestMappingInfo对象中。对handler的所有方法过滤完成之后,就要遍历这些方法,以一定的方式存储起来。?

Java代码??收藏代码

  1. /**?

  2. ?????*?Register?a?handler?method?and?its?unique?mapping.?

  3. [email protected]or?the?handler?instance?

  4. [email protected]

  5. [email protected]d?with?the?handler?method?

  6. [email protected]?was?already?registered?

  7. ?????*?under?the?same?mapping?

  8. ?????*/??

  9. ????protected?void?registerHandlerMethod(Object?handler,?Method?method,?T?mapping)?{??

  10. ????????HandlerMethod?newHandlerMethod?=?createHandlerMethod(handler,?method);??

  11. ????????HandlerMethod?oldHandlerMethod?=?this.handlerMethods.get(mapping);??

  12. ????????if?(oldHandlerMethod?!=?null?&&?!oldHandlerMethod.equals(newHandlerMethod))?{??

  13. ????????????throw?new?IllegalStateException("Ambiguous?mapping?found.?Cannot?map?'"?+?newHandlerMethod.getBean()?+??

  14. ????????????????????"'?bean?method?\n"?+?newHandlerMethod?+?"\nto?"?+?mapping?+?":?There?is?already?'"?+??

  15. ????????????????????oldHandlerMethod.getBean()?+?"'?bean?method\n"?+?oldHandlerMethod?+?"?mapped.");??

  16. ????????}??

  17. ??

  18. ????????this.handlerMethods.put(mapping,?newHandlerMethod);??

  19. ????????if?(logger.isInfoEnabled())?{??

  20. ????????????logger.info("Mapped?\""?+?mapping?+?"\"?onto?"?+?newHandlerMethod);??

  21. ????????}??

  22. ??

  23. ????????Set<String>?patterns?=?getMappingPathPatterns(mapping);??

  24. ????????for?(String?pattern?:?patterns)?{??

  25. ????????????if?(!getPathMatcher().isPattern(pattern))?{??

  26. ????????????????this.urlMap.add(pattern,?mapping);??

  27. ????????????}??

  28. ????????}??

  29. ????}??


这里的this.handlerMethods就包含了所有管辖的bean,key为RequestMappingInfo对象,[email protected]d构建的HandlerMethod。?
如下所示:
?

Java代码??收藏代码

  1. /**?

  2. ?????*?Create?the?HandlerMethod?instance.?

  3. [email protected]al?handler?instance?

  4. [email protected]

  5. [email protected]

  6. ?????*/??

  7. ????protected?HandlerMethod?createHandlerMethod(Object?handler,?Method?method)?{??

  8. ????????HandlerMethod?handlerMethod;??

  9. ????????if?(handler?instanceof?String)?{??

  10. ????????????String?beanName?=?(String)?handler;??

  11. ????????????handlerMethod?=?new?HandlerMethod(beanName,?getApplicationContext(),?method);??

  12. ????????}??

  13. ????????else?{??

  14. ????????????handlerMethod?=?new?HandlerMethod(handler,?method);??

  15. ????????}??

  16. ????????return?handlerMethod;??

  17. ????}??


至此,RequestMappingHandlerMapping的初始化注册工作就完成了。然后就是等待请求,访问?
http://localhost:8080/string?name=aa,RequestMappingHandlerMapping会匹配到由StringAction对象和它的包含注释的方法testMessageConverter构建的HandlerMethod对象,该对象将作为handler,然后再遍历HandlerAdapter判断它们是否支持这个handler,RequestMappingHandlerAdapter的判断依据为是否是HandlerMethod 类型(在AbstractHandlerMethodAdapter类中):
?

Java代码??收藏代码

  1. public?final?boolean?supports(Object?handler)?{??

  2. ????????return?handler?instanceof?HandlerMethod?&&?supportsInternal((HandlerMethod)?handler);??

  3. ????}??

  4. ?

  相关解决方案