美文网首页
7、SpringMVC拦截器源码分析

7、SpringMVC拦截器源码分析

作者: 那谁319 | 来源:发表于2019-06-02 14:28 被阅读0次

    拦截器执行节点

    • Web请求被DispatcherServlet截获后,会调用DispatcherServlet的doDispatch方法。

    DispatcherServlet.doDispatch执行逻辑

    DispatcherServlet.doDispatch.png
    • 简单梳理doDispatch的执行流程
      • 获取Handler
      • 获取Adapter
      • 执行applyPreHandle,(调用HandlerExecutionChain的applyPreHandle方法)
      • 执行handle方法
      • 执行applyPostHandle,(调用HandlerExecutionChain的applyPostHandle方法)
      • 异常处理,(调用HandlerExecutionChain的triggerAfterCompletion方法)
      • 处理返回结果

    HandlerExecutionChain的applyPreHandle方法执行逻辑

    HandlerExecutionChain.applyPreHandle.png
    • 循环执行所有的拦截器的preHandle方法,返回结果为false会执行triggerAfterCompletion方法。

    HandlerExecutionChain的applyPostHandle方法执行逻辑

    HandlerExecutionChain.applyPostHandle.png
    • 循环执行所有的拦截器的postHandle方法。

    HandlerExecutionChain的triggerAfterCompletion方法执行逻辑

    HandlerExecutionChain.triggerAfterCompletion.png
    • 循环执行所有的拦截器的afterCompletion方法。

    问题汇总

    • 从以上的源码者可以看出拦截器的执行流程。但是这些一下问题似乎没有回答:
      • 1、拦截器何时创建的?
      • 2、这些拦截器又是什么时候被HandlerExecutionChain对象所持有的呢?
      • 3、一个请求过来该执行那些拦截器是什么时候确定的?

    一份配置demo

    interceptors.png

    MvcNamespaceHandler.init()执行逻辑

    namespaceHandler-init.png
    • 从初始化的解析器列表来看,对照配置demo,重点关注interceptors元素匹配的解析器InterceptorsBeanDefinitionParser。

    InterceptorsBeanDefinitionParser.parse(参数)执行逻辑

    nterceptorsBeanDefinitionParser.parse.png
    • 简单总结下parse方法主要是注册自定义拦截器bean。

    获取Handler(HandlerExecutionChain)

    • 我们知道doDispatch的执行流程中会首先获取Handler,我们看下获取Handler的执行逻辑。


      DispatcherServlet.getHandler.png
    • 循环比遍历已经初始化的handlerMappings,调用handlerMapping的getHandler方法。
    AbstractHandlerMapping.getHandler.png
    • 根据request参数获取对应的HandlerMethod对象;
    • 调用getHandlerExecutionChain方法。
    AbstractHandlerMapping.getHandlerExecutionChain.png
    • 判断参数handler是否匹配HandlerExecutionChain,如果是把参数handler赋值给HandlerExecutionChain对象chain,如果不是new HandlerExecutionChain(handler);
    • 获取请求path,循环遍历adaptedInterceptors集合,添加匹配路径的拦截器到HandlerExecutionChain对象。
    MappedInterceptor.matches.png
    • 可以看到拦截器的匹配是根据指定includePatterns和excludePatterns做条件进行匹配和过滤。

    AbstractHandlerMapping的adaptedInterceptors 属性

    • 从上面的代码中我们看到HandlerExecutionChain对象持有的当前请求匹配的拦截器是从AbstractHandlerMapping的adaptedInterceptors 属性获取的,那么AbstractHandlerMapping的adaptedInterceptors 属性是什么时候被赋值的呢?
    • adaptedInterceptors既然是AbstractHandlerMapping的属性,我们清楚的是其子类RequestMappingHandlerMapping对象,所以adaptedInterceptors属性的赋值,应该和RequestMappingHandlerMapping的加载有关。
    • 从XmlWebApplicationContext.refresh()执行逻辑中我们知道RequestMappingHandlerMapping类会被懒加载。而spring在执行refresh()逻辑时会添加实现BeanPostProcessor接口的ApplicationContextAwareProcessor,在后续bean加载完成前后会调用postProcessBeforeInitialization和postProcessAfterInitialization方法。其中postProcessBeforeInitialization逻辑中会通过判断当前实例化的bean是否ApplicationContextAware,如果匹配则执行 ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);

    RequestMappingHandlerMapping类继承关系

    RequestMappingHandlerMapping.png
    • 由RequestMappingHandlerMapping的类继承图可以看到,其实现了ApplicationContextAware接口,所以当RequestMappingHandlerMapping被懒加载时会执行((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
    ApplicationObjectSupport.setApplicationContext.png
    • 主要调用initApplicationContext(ApplicationContext context)方法。
    ApplicationObjectSupport.initApplicationContext.png
    • 调用子类AbstractHandlerMapping重写的initApplicationContext()方法。
    AbstractHandlerMapping.initApplicationContext.png
    • 给adaptedInterceptors赋值;
    • 并初始化所有的拦截器。

    相关文章

      网友评论

          本文标题:7、SpringMVC拦截器源码分析

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