springmvc进阶(3):mvc:annotation-driven详解

在spring中所有的自定义命名空间(像mvc,context等)下的标签解析都是由BeanDefinitionParser接口的子类来完成的。那么就找到<context:component-scan/>标签的解析类,看看是如何解析的。

BeanDefinitionParser接口的实现类:
这里写图片描述

我们看到有多个AnnotationDrivenBeanDefinitionParser,他们是用来处理不同命名空间下的标签的,我们今天研究的是<mvc:annotation-driven/>标签,所以我们找到对应的实现类是org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser

对于一个陌生的类,首先要先去看它的Javadoc:

 * A {@link BeanDefinitionParser} that provides the configuration for the
 * {@code <annotation-driven/>} MVC namespace element.
 *  * <p>This class registers the following {@link HandlerMapping}s:</p>
 * <ul>
 * <li>{@link RequestMappingHandlerMapping}
 * ordered at 0 for mapping requests to annotated controller methods.
 * <li>{@link BeanNameUrlHandlerMapping}
 * ordered at 2 to map URL paths to controller bean names.
 * </ul>
 *  * <p><strong>Note:</strong> Additional HandlerMappings may be registered
 * as a result of using the {@code <view-controller>} or the
 * {@code <resources>} MVC namespace elements.
 *  * <p>This class registers the following {@link HandlerAdapter}s:
 * <ul>
 * <li>{@link RequestMappingHandlerAdapter}
 * for processing requests with annotated controller methods.
 * <li>{@link HttpRequestHandlerAdapter}
 * for processing requests with {@link HttpRequestHandler}s.
 * <li>{@link SimpleControllerHandlerAdapter}
 * for processing requests with interface-based {@link Controller}s.
 * </ul>
 *  * <p>This class registers the following {@link HandlerExceptionResolver}s:
 * <ul>
 * <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions
 * through @{@link ExceptionHandler} methods.
 * <li>{@link ResponseStatusExceptionResolver} for exceptions annotated
 * with @{@link ResponseStatus}.
 * <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring
 * exception types
 * </ul>
 *  * <p>This class registers an {@link org.springframework.util.AntPathMatcher}
 * and a {@link org.springframework.web.util.UrlPathHelper} to be used by:
 * <ul>
 * <li>the {@link RequestMappingHandlerMapping},
 * <li>the {@link HandlerMapping} for ViewControllers
 * <li>and the {@link HandlerMapping} for serving resources
 * </ul>
 * Note that those beans can be configured by using the {@code path-matching} MVC namespace element.
 *  * <p>Both the {@link RequestMappingHandlerAdapter} and the
 * {@link ExceptionHandlerExceptionResolver} are configured with instances of
 * the following by default:
 * <ul>
 * <li>A {@link ContentNegotiationManager}
 * <li>A {@link DefaultFormattingConversionService}
 * <li>A {@link org.springframework.validation.beanvalidation.LocalValidatorFactoryBean}
 * if a JSR-303 implementation is available on the classpath
 * <li>A range of {@link HttpMessageConverter}s depending on what 3rd party
 * libraries are available on the classpath.
 * </ul>

该注释文档说明该解析器向容器中注入了如下组件:

  • HandlerMapping :请求映射
    1、RequestMappingHandlerMapping
         支持@RequestMapping注解

    2、BeanNameUrlHandlerMapping
         将controller类的名字映射为请求url

  • HandlerAdapter : 请求处理
    1、RequestMappingHandlerAdapter
         处理@Controller和@RequestMapping注解的处理器
    2、HttpRequestHandlerAdapter
          处理继承了HttpRequestHandler创建的处理器
    3、SimpleControllerHandlerAdapter
         处理继承自Controller接口的处理器

  • ExceptionResolver:处理异常的解析器
    1、ExceptionHandlerExceptionResolver
    2、ResponseStatusExceptionResolver
    3、DefaultHandlerExceptionResolver

代码如下:

@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
    ...
    parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, methodMappingName));
    parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, handlerAdapterName));
    parserContext.registerComponent(new BeanComponentDefinition(uriCompContribDef, uriCompContribName));
    parserContext.registerComponent(new BeanComponentDefinition(exceptionHandlerExceptionResolver, methodExceptionResolverName));
    parserContext.registerComponent(new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName));
    parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExceptionResolverName));
    parserContext.registerComponent(new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName));

    // Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
    MvcNamespaceUtils.registerDefaultComponents(parserContext, source);

    parserContext.popAndRegisterContainingComponent();

    ...
}

上面省略大量代码,这里只贴出部分注册组件的代码部分。
其中

// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
MvcNamespaceUtils.registerDefaultComponents(parserContext, source);

这个将容器默认mapping和adapter加进来:

public static void registerDefaultComponents(ParserContext parserContext, Object source) {
    registerBeanNameUrlHandlerMapping(parserContext, source);
    registerHttpRequestHandlerAdapter(parserContext, source);
    registerSimpleControllerHandlerAdapter(parserContext, source);
}

总结
这里来说说配置开启的两个常用的组件,RequestMappingHandlerMapping和RequestMappingHandlerAdapter。

  • RequestMappingHandlerMapping是HandlerMapping的实现类,它会在容器启动的时候,扫描容器内的bean,解析带有@RequestMapping
    注解的方法,并将其解析为url和handlerMethod键值对方式注册到请求映射表中。
  • RequestMappingHandlerAdapter是HandlerAdapter的实现类,它是处理请求的适配器,说白了,就是确定调用哪个类的哪个方法,并且构造方法参数,返回值。

像其实<context:component-scan/>标签是告诉Spring容器来扫描指定包下的类,并注册被@Component,@Controller,@Service,@Repository等注解标记的组件相似。
<mvc:annotation-driven/>是告知Spring容器,我们启用注解驱动,支持@RequestMapping注解,这样我们就可以使用@RequestMapping来配置处理器。

猜你喜欢

转载自blog.csdn.net/abc997995674/article/details/80511545