标签

作者: goldfather | 来源:发表于2018-12-06 16:26 被阅读0次

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

    BeanDefinitionParser接口的实现类:


    我们看到有多个AnnotationDrivenBeanDefinitionParser,他们是用来处理不同命名空间下的标签的,我们今天研究的是<mvc:annotation-driven/>标签,所以我们找到对应的实现类是org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser
    该注释文档说明该解析器向容器中注入了如下组件:

    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();
    
        ...
    }
    

    这个将容器默认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来配置处理器。

    相关文章

      网友评论

          本文标题:标签

          本文链接:https://www.haomeiwen.com/subject/papocqtx.html