一、AnnotationDrivenBeanDefinitionParser

通常如果我们希望通过注解的方式来进行spring MVC开发,我们都会在***-servlet.xml中加入<mvc:annotation-driven/>标签来告诉Spring我们的目的。但是我们为什么这么做呢?这个标签是什么意思呢?它做了什么呢?

    同样为了弄清楚这些问题, 像<context:component-scan/>标签一样,我们先找到它的解析类。第一篇文章中说过了,所有的自定义命名空间(像mvc,context等)下的标签解析都是由BeanDefinitionParser接口的子类来完成的。参看第一篇文章中的图片

SpringMVC 解读之<mvc:annotation-driven/>标签_spring


我们看到有多个AnnotationDrivenBeanDefinitionParser,他们是用来处理不同命名空间下的<annotation-driven/>标签的,我们今天研究的是<mvc:annotation-driven/>标签,所以我们找到对应的实现类是org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser。
    通过阅读类注释文档,我们发现这个类主要是用来向工厂中注册了

​​RequestMappingHandlerMapping​​
​​BeanNameUrlHandlerMapping​​​​RequestMappingHandlerAdapter​​
​​HttpRequestHandlerAdapter​​​​SimpleControllerHandlerAdapter​​​​ExceptionHandlerExceptionResolver​​
​​ResponseStatusExceptionResolver​​
​​DefaultHandlerExceptionResolver​​

上面几个Bean实例。这几个类都是用来做什么的呢?

    前两个是HandlerMapping接口的实现类,用来处理请求映射的。其中第一个是处理@RequestMapping注解的。第二个会将controller类的名字映射为请求url。

    中间三个是用来处理请求的。具体点说就是确定调用哪个controller的哪个方法来处理当前请求。第一个处理@Controller注解的处理器,支持自定义方法参数和返回值(很酷)。第二个是处理继承HttpRequestHandler的处理器。第三个处理继承自Controller接口的处理器。

    后面三个是用来处理异常的解析器。

二、实现

光说无凭据,我们直接看代码:


1. public BeanDefinition parse(Element element, ParserContext parserContext) {  
2. Object source = parserContext.extractSource(element);
3.
4. new CompositeComponentDefinition(element.getTagName(), source);
5. parserContext.pushContainingComponent(compDefinition);
6.
7. RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager(element, source, parserContext);
8. //第一个在这 RequestMappingHandlerMapping
9. new RootBeanDefinition(RequestMappingHandlerMapping.class);
10. handlerMappingDef.setSource(source);
11. handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
12. "order", 0);
13. "removeSemicolonContent", false);
14. "contentNegotiationManager", contentNegotiationManager);
15. String methodMappingName = parserContext.getReaderContext().registerWithGeneratedName(handlerMappingDef);
16. //第二个在这 RequestMappingHandlerAdapter
17. new RootBeanDefinition(RequestMappingHandlerAdapter.class);
18. handlerAdapterDef.setSource(source);
19. handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
20. "contentNegotiationManager", contentNegotiationManager);
21. "webBindingInitializer", bindingDef);
22. "messageConverters", messageConverters);
23. if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {
24. "ignoreDefaultModelOnRedirect"));
25. "ignoreDefaultModelOnRedirect", ignoreDefaultModel);
26. }
27. if (argumentResolvers != null) {
28. "customArgumentResolvers", argumentResolvers);
29. }
30. if (returnValueHandlers != null) {
31. "customReturnValueHandlers", returnValueHandlers);
32. }
33. if (asyncTimeout != null) {
34. "asyncRequestTimeout", asyncTimeout);
35. }
36. if (asyncExecutor != null) {
37. "taskExecutor", asyncExecutor);
38. }
39. "callableInterceptors", callableInterceptors);
40. "deferredResultInterceptors", deferredResultInterceptors);
41. String handlerAdapterName = parserContext.getReaderContext().registerWithGeneratedName(handlerAdapterDef);
42. //异常处理解析器
43. new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
44. exceptionHandlerExceptionResolver.setSource(source);
45. exceptionHandlerExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
46. "contentNegotiationManager", contentNegotiationManager);
47. "messageConverters", messageConverters);
48. "order", 0);
49. String methodExceptionResolverName =
50. parserContext.getReaderContext().registerWithGeneratedName(exceptionHandlerExceptionResolver);
51. //异常处理解析器
52. new RootBeanDefinition(ResponseStatusExceptionResolver.class);
53. responseStatusExceptionResolver.setSource(source);
54. responseStatusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
55. "order", 1);
56. String responseStatusExceptionResolverName =
57. parserContext.getReaderContext().registerWithGeneratedName(responseStatusExceptionResolver);
58. //异常处理解析器
59. new RootBeanDefinition(DefaultHandlerExceptionResolver.class);
60. defaultExceptionResolver.setSource(source);
61. defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
62. "order", 2);
63. String defaultExceptionResolverName =
64. parserContext.getReaderContext().registerWithGeneratedName(defaultExceptionResolver);
65.
66. new BeanComponentDefinition(handlerMappingDef, methodMappingName));
67. new BeanComponentDefinition(handlerAdapterDef, handlerAdapterName));
68. new BeanComponentDefinition(exceptionHandlerExceptionResolver, methodExceptionResolverName));
69. new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName));
70. new BeanComponentDefinition(defaultExceptionResolver, defaultExceptionResolverName));
71. new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName));
72. //这里注册了BeanNameUrlHandlerMapping,SimpleControllerHandlerAdapter等
73. // Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
74. MvcNamespaceUtils.registerDefaultComponents(parserContext, source);
75.
76. parserContext.popAndRegisterContainingComponent();
77.
78. return null;
79. }
80. //在这啊。
81. public static void registerDefaultComponents(ParserContext parserContext, Object source) {
82. registerBeanNameUrlHandlerMapping(parserContext, source);
83. registerHttpRequestHandlerAdapter(parserContext, source);
84. registerSimpleControllerHandlerAdapter(parserContext, source);
85. }

略长,但很容易看明白的代码。看注释我们发现,它的确注册了上面说的那几个类。



三、总结

我们知道了它们自动为我们注册了这么多的Bean,那这些Bean是做什么的呢?

    我们主要说明里面的两个,RequestMappingHandlerMapping和RequestMappingHandlerAdapter。

    第一个是HandlerMapping的实现类,它会处理@RequestMapping 注解,并将其注册到请求映射表中。

    第二个是HandlerAdapter的实现类,它是处理请求的适配器,说白了,就是确定调用哪个类的哪个方法,并且构造方法参数,返回值。

    那么它跟<context:component-scan/>有什么区别呢?<context:component-scan/>标签是告诉Spring 来扫描指定包下的类,并注册被@Component,@Controller,@Service,@Repository等注解标记的组件。

    而<mvc:annotation-driven/>是告知Spring,我们启用注解驱动。然后Spring会自动为我们注册上面说到的几个Bean到工厂中,来处理我们的请求。