zoukankan      html  css  js  c++  java
  • SpringMVC源码阅读HandlerMapping初始化-AbstractHandlerMapping(五)

    接口

     public interface HandlerMapping {
            /**
             * 根据requst获得 对应的Handler
             * @param var1
             * @return
             * @throws Exception
             */
            HandlerExecutionChain getHandler(HttpServletRequest var1) throws Exception;
        }

    类图

     1.我们常用的方式就是RequestMappingHandlerMapping  通过配置注解的方式@Contorller  @RequestMapping

    2.BeanNameUrlHandlerMapping 配置方式很少使用 摘自:https://www.cnblogs.com/suanshun/p/6700200.html

    ApplicationObjectSupport

    setApplicationContext

    org.springframework.context.support.ApplicationObjectSupport#setApplicationContext

    注意看上面继承关系 spring初始化因为实现了ApplicationContextAware 所以会调用setApplicationContext

    public abstract class ApplicationObjectSupport implements ApplicationContextAware {
    }
    public final void setApplicationContext(@Nullable ApplicationContext context) throws BeansException {
            if (context == null && !this.isContextRequired()) {
                this.applicationContext = null;
                this.messageSourceAccessor = null;
            } else if (this.applicationContext == null) {
                if (!this.requiredContextClass().isInstance(context)) {
                    throw new ApplicationContextException("Invalid application context: needs to be of type [" + this.requiredContextClass().getName() + "]");
                }
    
                this.applicationContext = context;
                this.messageSourceAccessor = new MessageSourceAccessor(context);
                //<1>调用当前类的initApplicationContext 是个空实现 WebApplicationObjectSupport  重写了所以这里调用的是WebApplicationObjectSupport的
                this.initApplicationContext(context);
            } else if (this.applicationContext != context) {
                throw new ApplicationContextException("Cannot reinitialize with different application context: current one is [" + this.applicationContext + "], passed-in one is [" + context + "]");
            }
    
        }

    WebApplicationObjectSupport

    <1>initApplicationContext

    org.springframework.context.support.ApplicationObjectSupport#setApplicationContext

    ->

    org.springframework.web.context.support.WebApplicationObjectSupport#initApplicationContext

     protected void initApplicationContext(ApplicationContext context) {
            //<2>调用父类的初始化动作 
            super.initApplicationContext(context);
            if (this.servletContext == null && context instanceof WebApplicationContext) {
                this.servletContext = ((WebApplicationContext)context).getServletContext();
                if (this.servletContext != null) {
                    //空实现 子类并没有任何实现 如果我们想做一些自定义操作可以实现此方法
                    this.initServletContext(this.servletContext);
                }
            }
    
        }

    <2>initApplicationContext

    org.springframework.context.support.ApplicationObjectSupport#setApplicationContext

    ->

    org.springframework.web.context.support.WebApplicationObjectSupport#initApplicationContext

    ->

    org.springframework.context.support.ApplicationObjectSupport#initApplicationContext(org.springframework.context.ApplicationContext)

    protected void initApplicationContext(ApplicationContext context) throws BeansException {
            //<3>注 当前类是空实现 被AbstractHandlerMapping 重写了 所以是调用的AbstractHandlerMapping的
            this.initApplicationContext();
        }

    AbstractHandlerMapping

    <3>initApplicationContext

    org.springframework.context.support.ApplicationObjectSupport#setApplicationContext

    ->

    org.springframework.web.context.support.WebApplicationObjectSupport#initApplicationContext

    ->

    org.springframework.context.support.ApplicationObjectSupport#initApplicationContext(org.springframework.context.ApplicationContext)

    ->

    org.springframework.web.servlet.handler.AbstractHandlerMapping#initApplicationContext

     protected void initApplicationContext() throws BeansException {
            //<4>空实现  传入拦截器集合 我们重写可以 往集合add拦截器
            this.extendInterceptors(this.interceptors);
            //<5>从spring容器获取mappedInterceptor
            this.detectMappedInterceptors(this.adaptedInterceptors);
            //<6>初始化拦截器
            this.initInterceptors();
        }

    <4>使用例子

    这个是我找的AbstractWebMvcEndpointHandlerMapping 的实现类

       protected void extendInterceptors(List<Object> interceptors) {
            interceptors.add(new SkipPathExtensionContentNegotiation());
        }

    <5>detectMappedInterceptors

    org.springframework.web.context.support.WebApplicationObjectSupport#initApplicationContext

    ->

    org.springframework.context.support.ApplicationObjectSupport#initApplicationContext(org.springframework.context.ApplicationContext)

    ->

    org.springframework.web.servlet.handler.AbstractHandlerMapping#initApplicationContext

    ->

    org.springframework.web.servlet.handler.AbstractHandlerMapping#detectMappedInterceptors

        protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) {
    
            /**
             * xml配置方式
             * <mvc:interceptor>
             *             <mvc:mapping path="/login/.do "/> < bean class="com.bozhi.rest.interceptor.DataCollectInterceptor" ></bean>
             * </mvc:interceptor >
             * 我们也可以通过config方式创建MappedInterceptor到容器
             */
            mappedInterceptors.addAll(BeanFactoryUtils.beansOfTypeIncludingAncestors(this.getApplicationContext(), MappedInterceptor.class, true, false).values());
        }
    }

    <6>initInterceptors

       protected void initInterceptors() {
            if (!this.interceptors.isEmpty()) {
                for (int i = 0; i < this.interceptors.size(); ++i) {
                    Object interceptor = this.interceptors.get(i);
                    if (interceptor == null) {
                        throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
                    }
                    //内部会判断拦截器是否是WebRequestInterceptor类型如果是 则用WebRequestHandlerInterceptorAdapter 代理
                    this.adaptedInterceptors.add(this.adaptInterceptor(interceptor));
                }
            }
        }
        protected HandlerInterceptor adaptInterceptor(Object interceptor) {
            if (interceptor instanceof HandlerInterceptor) {
                return (HandlerInterceptor)interceptor;
            } else if (interceptor instanceof WebRequestInterceptor) {
                return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor)interceptor);
            } else {
                throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName());
            }
        }

    到这里Abstract的初始化任务就完成了

    总结

    1.AbstractHandle通过实现了spring 的ApplicationContextAware接口 通过setApplicationContext 做一些初始化动作

    2.做初始化MappedInterceptor的动作

    3.预留一些以下扩展点

                我们可以通过重写initServletContext 做初始化ServletContext的动作

                 我们可以通过重写extendInterceptors做初始化拦截器的动作

  • 相关阅读:
    内联函数与宏定义
    三色塔汉诺塔 三色
    Volatile C
    阶乘 简单递归实现
    双色汉诺塔 算法 (递归)
    向上向下排序
    Convert、Parse、TryParse、(int)等区别
    ToString()、Convert.ToString()、(string)、as string 的区别[转]
    ASP.NET页面刷新方法大集合
    getElementByID,getElementsByName,getElementsByTagName的区别
  • 原文地址:https://www.cnblogs.com/LQBlog/p/12216740.html
Copyright © 2011-2022 走看看