通常如果我们希望通过注解的方式来进行Spring MVC开发,我们都会在***-servlet.xml中加入<mvc:annotation-driven/>标签来告诉Spring我们的目的。但是我们为什么这
么做呢?这个标签是什么意思呢?它做了什么呢?
同样为了弄清楚这些问题, 像<context:component-scan/>标签一样,我们先找到它的解析类。所有的自定义命名空间(像mvc,context等)下的标签解析都是由
BeanDefinitionParser接口的子类来完成的.
我们看到有多个AnnotationDrivenBeanDefinitionParser,他们是用来处理不同命名空间下的<annotation-driven/>标签的,我们今天研究的是<mvc:annotation-driven/>标
签,所以我们找到对应的实现类是org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser。
通过阅读类注释文档,我们发现这个类主要是用来向工厂中注册了RequestMappingHandlerMappingde、BeanNameUrlHandlerMappingde、RequestMappingHandlerAdapterde、HttpRequestHandlerAdapterde、SimpleControllerHandlerAdapterde、ExceptionHandlerExceptionResolverde、ResponseStatusExceptionResolverde、DefaultHandlerExceptionResolverde。上面几个Bean实例。这几个类都是用来做什么的呢?
光说无凭据,我们直接看代码:
public BeanDefinition parse(Element element, ParserContext parserContext) { <span style="white-space:pre"> </span> Object source = parserContext.extractSource(element); <span style="white-space:pre"> </span>CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source); <span style="white-space:pre"> </span>parserContext.pushContainingComponent(compDefinition); <span style="white-space:pre"> </span>RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager(element, source, parserContext); <span style="white-space:pre"> </span>//第一个在这 RequestMappingHandlerMapping <span style="white-space:pre"> </span>RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class); <span style="white-space:pre"> </span>handlerMappingDef.setSource(source); <span style="white-space:pre"> </span>handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); <span style="white-space:pre"> </span>handlerMappingDef.getPropertyValues().add("order", 0); <span style="white-space:pre"> </span>handlerMappingDef.getPropertyValues().add("removeSemicolonContent", false); <span style="white-space:pre"> </span>handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager); <span style="white-space:pre"> </span>String methodMappingName = parserContext.getReaderContext().registerWithGeneratedName(handlerMappingDef); <span style="white-space:pre"> </span>//第二个在这 RequestMappingHandlerAdapter <span style="white-space:pre"> </span>RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); <span style="white-space:pre"> </span>handlerAdapterDef.setSource(source); <span style="white-space:pre"> </span>handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); <span style="white-space:pre"> </span>handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager); <span style="white-space:pre"> </span>handlerAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef); <span style="white-space:pre"> </span>handlerAdapterDef.getPropertyValues().add("messageConverters", messageConverters); <span style="white-space:pre"> </span>if (element.hasAttribute("ignoreDefaultModelOnRedirect")) { <span style="white-space:pre"> </span>Boolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute("ignoreDefaultModelOnRedirect")); <span style="white-space:pre"> </span>handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>if (argumentResolvers != null) { <span style="white-space:pre"> </span>handlerAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>if (returnValueHandlers != null) { <span style="white-space:pre"> </span>handlerAdapterDef.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>if (asyncTimeout != null) { <span style="white-space:pre"> </span>handlerAdapterDef.getPropertyValues().add("asyncRequestTimeout", asyncTimeout); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>if (asyncExecutor != null) { <span style="white-space:pre"> </span>handlerAdapterDef.getPropertyValues().add("taskExecutor", asyncExecutor); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors); <span style="white-space:pre"> </span>handlerAdapterDef.getPropertyValues().add("deferredResultInterceptors", deferredResultInterceptors); <span style="white-space:pre"> </span>String handlerAdapterName = parserContext.getReaderContext().registerWithGeneratedName(handlerAdapterDef); <span style="white-space:pre"> </span>//异常处理解析器 <span style="white-space:pre"> </span>RootBeanDefinition exceptionHandlerExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class); <span style="white-space:pre"> </span>exceptionHandlerExceptionResolver.setSource(source); <span style="white-space:pre"> </span>exceptionHandlerExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); <span style="white-space:pre"> </span>exceptionHandlerExceptionResolver.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager); <span style="white-space:pre"> </span>exceptionHandlerExceptionResolver.getPropertyValues().add("messageConverters", messageConverters); <span style="white-space:pre"> </span>exceptionHandlerExceptionResolver.getPropertyValues().add("order", 0); <span style="white-space:pre"> </span>String methodExceptionResolverName = <span style="white-space:pre"> </span>parserContext.getReaderContext().registerWithGeneratedName(exceptionHandlerExceptionResolver); <span style="white-space:pre"> </span>//异常处理解析器 <span style="white-space:pre"> </span>RootBeanDefinition responseStatusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class); <span style="white-space:pre"> </span>responseStatusExceptionResolver.setSource(source); <span style="white-space:pre"> </span>responseStatusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); <span style="white-space:pre"> </span>responseStatusExceptionResolver.getPropertyValues().add("order", 1); <span style="white-space:pre"> </span>String responseStatusExceptionResolverName = <span style="white-space:pre"> </span>parserContext.getReaderContext().registerWithGeneratedName(responseStatusExceptionResolver); <span style="white-space:pre"> </span>//异常处理解析器 <span style="white-space:pre"> </span>RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class); <span style="white-space:pre"> </span>defaultExceptionResolver.setSource(source); <span style="white-space:pre"> </span>defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); <span style="white-space:pre"> </span>defaultExceptionResolver.getPropertyValues().add("order", 2); <span style="white-space:pre"> </span>String defaultExceptionResolverName = <span style="white-space:pre"> </span>parserContext.getReaderContext().registerWithGeneratedName(defaultExceptionResolver); <span style="white-space:pre"> </span>parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, methodMappingName)); <span style="white-space:pre"> </span>parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, handlerAdapterName)); <span style="white-space:pre"> </span>parserContext.registerComponent(new BeanComponentDefinition(exceptionHandlerExceptionResolver, methodExceptionResolverName)); <span style="white-space:pre"> </span>parserContext.registerComponent(new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName)); <span style="white-space:pre"> </span>parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExceptionResolverName)); <span style="white-space:pre"> </span>parserContext.registerComponent(new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName)); <span style="white-space:pre"> </span>//这里注册了BeanNameUrlHandlerMapping,SimpleControllerHandlerAdapter等 <span style="white-space:pre"> </span>// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off" <span style="white-space:pre"> </span>MvcNamespaceUtils.registerDefaultComponents(parserContext, source); <span style="white-space:pre"> </span>parserContext.popAndRegisterContainingComponent(); <span style="white-space:pre"> </span>return null; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>//在这啊。 public static void registerDefaultComponents(ParserContext parserContext, Object source) { <span style="white-space:pre"> </span>registerBeanNameUrlHandlerMapping(parserContext, source); <span style="white-space:pre"> </span>registerHttpRequestHandlerAdapter(parserContext, source); <span style="white-space:pre"> </span>registerSimpleControllerHandlerAdapter(parserContext, source); }
而<mvc:annotation-scan/>是告知Spring,我们启用注解驱动。然后Spring会自动为我们注册上面说到的几个Bean到工厂中,来处理我们的请求。