springmvc源码-Interceptor-源码分析

2,176 阅读3分钟

不要问我阅读spring源码有什么用,问就是没有用,只是让我自己使用spring的过程中自信点!

相关文章

spring-相关文章

相关链接

  1. spring-mvc-handlerMapping 是怎么存放我们的请求路径的-源码
  2. springmvc-执行流程
  3. spring-mvc 时如何选择 messageConverter
  4. springMVC-Interceptor-源码分析

本文主要记录自己学习过程,如有错误请指出

一.用法

1.常引用拦截器 : HandlerInterceptor

代码如下:

自己实现的拦截器
上图代码中 myMyHandlerInterceptor 注意:

  1. 实现HandlerInterceptor接口
  2. @Component 注解

现在spring-ioc 容器中已经存在我自己创建的拦截器,但是还要把它WebMvcConfigurationSupport(后面会讲为啥要交给它管理)

代码如下:

要完成对拦截器的使用,上图代码中注意两点:

  1. 重写 addInterceptors 方法
  2. @Configuration

上述做法之后可以使用 拦截器了

二.源码

看源码 逆向思维 -> 拦截器在哪里执行的 -> 拦截器是哪里来的

1.拦截在哪里执行的

  1. 我看到网上有很多说拦截器的实现原理是动态代理,其实并不是, aop的实现原理是动态代理
  2. 拦截器的实现原理是执行链 HandlerExecutionChain
  3. 这个过程是HandlerExecutionChain是spring-mvc(因为这个文章记录的是拦截器,不会多说springmvc的东西) 中产生的.

执行代码如下: org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)

上面代码中的标注1,2,3:

  1. 根据handlerMapping获取执行链HandlerExecutionChain(不同的请求映射关系是放在不懂的mapping中的,这里不同的请求指的是不同的controller或者是资源请求,这块是mvc的东西不多说了.),正常获取的mpping为requestMappingHandlerMapping
  2. 获取HandlerExecutionChain之后标注2的执行代码就是拦截器的执行

3. 标注3的执行代码正常的请求,此处不详解

2.拦截器从哪里来的

执行时期

  1. 获取所有的拦截器,发现拦截器是存放在 HandlerExecutionChain.interceptors中.
  2. HandlerExecutionChain 是在 org.springframework.web.servlet.DispatcherServlet.getHandler(HttpServletRequest)中返回的,说明HandlerExecutionChain.interceptors也是在这个时候别赋值的.
  3. DispatcherServlet.getHandler(HttpServletRequest)代码如下:

AbstractHandlerMapping.getHandlerExecutionChain(Object, HttpServletRequest)

说明 HandlerExecutionChain interceptors 是 从 AbstractHandlerMapping.adaptedInterceptors中拿得值

spring启动时期

现在我们知道了 执行的拦截器是从 AbstractHandlerMapping.adaptedInterceptors中拿到的

先看下AbstractHandlerMapping的结构,发现我们上面说到的requestMappinghandlerMapping是它的子类,这个也就是我们要讲的重点(requestMappinghandlerMapping的实例化过程)

这个地方先说下我看这段源码的思路

  1. 我们需要探究的是AbstractHandlerMapping.interceptors.因为我们getHandler中使用的是requestMappinghandlerMapping的实例.他们又是父子关系.所以interceptors是在requestMappingHandlerMapping实例化过程中被添加进去的.
  2. 思路到了这个地方,要知道,一个实例spring创建的过程: 放入BeanDefinitionMap -> getBean()(这里springIoc的源码不说了,以后有时间在写).
  3. 在getBean的执行地方debug 条件为BeanName.equals("requestMappingHandlerMapping"),发现不是通过构造器创建的,是根据@bean创建的.

发现是在WebMvcConfigurationSupport.requestMappingHandlerMapping()

AbstractHandlerMapping.setInterceptors(Object...)

WebMvcConfigurationSupport.getInterceptors()

看了上面的代码你会发现addInterceptors是被我们重写的

我们把自己的拦截器传给了这个方法.

总结:

拦截器是在springmvc处理请求的时候执行

是在执行链中存放的.

执行链中的 interceptors 是从AbstractHandlerMapping中拿到的.

AbstractHandlerMapping 中的 拦截器 是在 requestMappingHandlerMapping 初始化的过程存放的.

requestMappingHandlerMapping 初始化的时候 会调用 WebMvcConfigurationSupport 中的 addInterceptors()方法

这个方法被我们重写了,就是在使用 拦截器 的两个步骤中的 第二步 ,我们把自己写的拦截器传了进去