美文网首页源代码Spring boot
Spring MVC介绍(三)之 Annotation解析以及完

Spring MVC介绍(三)之 Annotation解析以及完

作者: 挂机的啊洋zzZ | 来源:发表于2019-02-25 22:37 被阅读33次
    spring.png

    Spring MVC介绍(三)之 Annotation解析以及完整的执行流程

    工作中对于Spring MVC我们最常用的还是使用注解的方式,那么对于注解Spring MVC的如何处理的?

    <context:component-scan base-package="com.demo.spring.mvc.control" />
    <mvc:annotation-driven/>
    
    一、annotation-driven

    在前面的介绍中,我们知道了HandlerMapping以及HandlerAdapter,那么annotation的是什么?

    对于注解:

    <mvc:annotation-driven/>
    

    它对应的handlerMapping则是:

    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
    

    对应的HandlerAdapter则是:

    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
    

    对应的Handler则是:

    org.springframework.web.method.HandlerMethod
    

    这些没有配置在配置文件中,注解是怎么实现的?

    来看下NamespaceHandler接口:

    org.springframework.beans.factory.xml.NamespaceHandler
    
    package org.springframework.beans.factory.xml;
    
    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    
    import org.springframework.beans.factory.config.BeanDefinition;
    import org.springframework.beans.factory.config.BeanDefinitionHolder;
    
    public interface NamespaceHandler {
    
        void init();
    
        BeanDefinition parse(Element element, ParserContext parserContext);
    
        BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext);
    
    }
    

    实现这个接口,则就可以动态的往ioc容器添加BeanDefinition,则就动态的添加了bean。

    那么这个是在哪实现的呢?

    来看下spring-webmvc包里面的spring.handlers

    org\springframework\spring-webmvc\4.3.8.RELEASE\spring-webmvc-4.3.8.RELEASE.jar!\META-INF\spring.handlers
    

    里面内容:

    http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
    

    点进去看一下 MvcNamespaceHandler 这个类:

    package org.springframework.web.servlet.config;
    
    import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
    
    public class MvcNamespaceHandler extends NamespaceHandlerSupport {
        public MvcNamespaceHandler() {
        }
    
        public void init() {
            this.registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
            this.registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
            this.registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
            this.registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
            this.registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
            this.registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
            this.registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
            this.registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
            this.registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
            this.registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
            this.registerBeanDefinitionParser("velocity-configurer", new VelocityConfigurerBeanDefinitionParser());
            this.registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
            this.registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
            this.registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
        }
    }
    

    此时我们看到了MvcNamespaceHandler extends NamespaceHandlerSupport

    public class MvcNamespaceHandler extends NamespaceHandlerSupport{...}
    

    NamespaceHandlerSupport implements NamespaceHandler

    public abstract class NamespaceHandlerSupport implements NamespaceHandler {}
    

    NamespaceHandler接口就是我们刚刚看到的那个动态注册BeanDefinition的接口。

    并且在MvcNamespaceHandler.init() 方法中,可以看到:

    this.registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
    

    并且 AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser

    class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {}
    

    其中 BeanDefinitionParser 接口:

    public interface BeanDefinitionParser {
    
    BeanDefinition parse(Element element, ParserContext parserContext);
    }
    

    AnnotationDrivenBeanDefinitionParser.parse() 的实现方法中,可以看到
    RequestMappingHandlerMapping 被注册到ioc容器中:

    RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
    

    同样的还有RequestMappingHandlerAdapter

    RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
    

    所以这就是为什么添加了 <mvc:annotation-driven/> 配置,就能实现mvc的整个配置了。

    二、MVC完整的执行流程

    之前我们介绍了MVC的异常处理和拦截器,那么加上这两部分,MVC的执行流程如下:

    DispatcherServlet ==> 找到下面这些组件(1:n)
    HandlerMapping ==> 基于url找到对应的handler (其实是找到HandlerExecutionChain)
    HandlerAdapter ==> 基于handler找到对应的适配器 调用handler返回ModelAndView
    (如果出现了异常)
    HandlerExceptionResovler ==> 处理异常 返回errorModelAndView
    (如果加入了拦截器)
    HandlerInterceptor ==> 处理拦截器
    ViewResolver   ==> 视图仓库 ==> 基于viewName找到View => 解析生成Html
    

    其中 DispatcherServlet 中调用 initStrategies 来初始化上述组件。

    org.springframework.web.servlet.DispatcherServlet#initStrategies
    
    protected void initStrategies(ApplicationContext context) {
        this.initMultipartResolver(context);
        this.initLocaleResolver(context);
        this.initThemeResolver(context);
        this.initHandlerMappings(context);
        this.initHandlerAdapters(context);
        this.initHandlerExceptionResolvers(context);
        this.initRequestToViewNameTranslator(context);
        this.initViewResolvers(context);
        this.initFlashMapManager(context);
    }
    

    有兴趣可以看下这些init方法实现。


    相关文章

      网友评论

        本文标题:Spring MVC介绍(三)之 Annotation解析以及完

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