7、SpringMVC拦截器源码分析

拦截器执行节点

  • 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拦截器源码分析)