不要问我阅读spring源码有什么用,问就是没有用,只是让我自己使用spring的过程中自信点!
相关文章
相关链接
- spring-mvc-handlerMapping 是怎么存放我们的请求路径的-源码
- springmvc-执行流程
- spring-mvc 时如何选择 messageConverter
- springMVC-Interceptor-源码分析
本文主要记录自己学习过程,如有错误请指出
一.用法
1.常引用拦截器 : HandlerInterceptor
代码如下:

- 实现HandlerInterceptor接口
- @Component 注解
现在spring-ioc 容器中已经存在我自己创建的拦截器,但是还要把它WebMvcConfigurationSupport(后面会讲为啥要交给它管理)
代码如下:

- 重写 addInterceptors 方法
- @Configuration
上述做法之后可以使用 拦截器了
二.源码
看源码 逆向思维 -> 拦截器在哪里执行的 -> 拦截器是哪里来的
1.拦截在哪里执行的
- 我看到网上有很多说拦截器的实现原理是动态代理,其实并不是, aop的实现原理是动态代理
- 拦截器的实现原理是执行链 HandlerExecutionChain
- 这个过程是HandlerExecutionChain是spring-mvc(因为这个文章记录的是拦截器,不会多说springmvc的东西) 中产生的.
执行代码如下: org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)

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

2.拦截器从哪里来的
执行时期
- 获取所有的拦截器,发现拦截器是存放在 HandlerExecutionChain.interceptors中.

- HandlerExecutionChain 是在 org.springframework.web.servlet.DispatcherServlet.getHandler(HttpServletRequest)中返回的,说明HandlerExecutionChain.interceptors也是在这个时候别赋值的.
- DispatcherServlet.getHandler(HttpServletRequest)代码如下:


AbstractHandlerMapping.getHandlerExecutionChain(Object, HttpServletRequest)

spring启动时期
现在我们知道了 执行的拦截器是从 AbstractHandlerMapping.adaptedInterceptors中拿到的
先看下AbstractHandlerMapping的结构,发现我们上面说到的requestMappinghandlerMapping是它的子类,这个也就是我们要讲的重点(requestMappinghandlerMapping的实例化过程)

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



WebMvcConfigurationSupport.getInterceptors()


总结:
拦截器是在springmvc处理请求的时候执行
是在执行链中存放的.
执行链中的 interceptors 是从AbstractHandlerMapping中拿到的.
AbstractHandlerMapping 中的 拦截器 是在 requestMappingHandlerMapping 初始化的过程存放的.
requestMappingHandlerMapping 初始化的时候 会调用 WebMvcConfigurationSupport 中的 addInterceptors()方法
这个方法被我们重写了,就是在使用 拦截器 的两个步骤中的 第二步 ,我们把自己写的拦截器传了进去