美文网首页
spring-mvc中,handlerMapping的初始化过程

spring-mvc中,handlerMapping的初始化过程

作者: 丫头可乐 | 来源:发表于2020-11-22 21:16 被阅读0次

    我们知道,在访问时,最终的请求都会经过下面的方法,有兴趣的同学可自行查看源代码,这里就不贴出来了。

    org.springframework.web.servlet.DispatcherServlet#doDispatch
    

    代码中的第一步就是,获取mappedHandler

    // Determine handler for the current request.
    mappedHandler = getHandler(processedRequest);
    

    我们查看getHandler方法的源码,如下

    org.springframework.web.servlet.DispatcherServlet#getHandler
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        if (this.handlerMappings != null) {
            for (HandlerMapping mapping : this.handlerMappings) {
                HandlerExecutionChain handler = mapping.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }
        return null;
    }
    

    发现,就是循环this.handlerMappings,从每个handlerMapping中,获取Handler。那么,this.handlerMappings是怎么初始化的?下面进行详细介绍。

    当我们使用springmvcservlet-servlet.xml作为spring-mvc的配置文件时,需要加上一个配置,如下:

    <mvc:annotation-driven/>
    

    很多同学可能从来没有细想过,为什么要加上这个东西

    在spring启动的过程当中,

    public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
    
                // Prepare this context for refreshing.
                prepareRefresh();
    
                // Tell the subclass to refresh the internal bean factory.
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
                // Prepare the bean factory for use in this context.
                prepareBeanFactory(beanFactory);
    
                try {
                    // Allows post-processing of the bean factory in context subclasses.
                    postProcessBeanFactory(beanFactory);
    
                    StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
                    // Invoke factory processors registered as beans in the context.
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    // Register bean processors that intercept bean creation.
                    registerBeanPostProcessors(beanFactory);
                    beanPostProcess.end();
    
                    // Initialize message source for this context.
                    initMessageSource();
    
                    // Initialize event multicaster for this context.
                    initApplicationEventMulticaster();
    
                    // Initialize other special beans in specific context subclasses.
                    onRefresh();
    
                    // Check for listener beans and register them.
                    registerListeners();
    
                    // Instantiate all remaining (non-lazy-init) singletons.
                    finishBeanFactoryInitialization(beanFactory);
    
                    // Last step: publish corresponding event.
                    finishRefresh();
                }
    
                catch (BeansException ex) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Exception encountered during context initialization - " +
                                "cancelling refresh attempt: " + ex);
                    }
    
                    // Destroy already created singletons to avoid dangling resources.
                    destroyBeans();
    
                    // Reset 'active' flag.
                    cancelRefresh(ex);
    
                    // Propagate exception to caller.
                    throw ex;
                }
    
                finally {
                    // Reset common introspection caches in Spring's core, since we
                    // might not ever need metadata for singleton beans anymore...
                    resetCommonCaches();
                    contextRefresh.end();
                }
            }
        }
    

    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    

    方法中,会对springmvcservlet-servlet.xml文件进行解析,当解析到mvc标签时,最终会读取到spring-webmvc模块下,resources/META-INF/spring.handler文件中内容。内容如下:

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

    拿到mvc标签的处理器

    org.springframework.web.servlet.config.MvcNamespaceHandler
    

    MvcNamespaceHandler中有一个初始化方法,我们可以查看一下,代码如下:

    public void init() {
            registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
            registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
            registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
            registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
            registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
            registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
            registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
            registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
            registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
            registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
            registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
            registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
            registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
    }
    

    我们可以看到annotation-driven名称后面,有一个解析

    AnnotationDrivenBeanDefinitionParser
    

    这个解析器是用来解析annotation-driven。在这里,初始化了HandleringMapping。将

    RequestMappingHandlerMapping
    BeanNameUrlHandlerMapping
    

    的beandefintion注册到了defaultlistablebeanfactory对象里面。

    最后,在spring启动的最后一步,会进行handlerMapping的初始化,将对象放入到HandleringMapping对象放入到this.handleringMappings列表中。

    // Last step: publish corresponding event.
    finishRefresh();
    

    相关文章

      网友评论

          本文标题:spring-mvc中,handlerMapping的初始化过程

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