本文主要記錄本身學習過程,若有錯誤請指出
一.用法
1.常引用攔截器 : HandlerInterceptor
代碼以下:web
上圖代碼中 myMyHandlerInterceptor 注意:
- 實現HandlerInterceptor接口
- @Component 註解
如今spring-ioc 容器中已經存在我本身建立的攔截器,可是還要把它WebMvcConfigurationSupport(後面會講爲啥要交給它管理)spring
代碼以下:spring-mvc
要完成對攔截器的使用,上圖代碼中注意兩點:
- 重寫 addInterceptors 方法
- @Configuration
上述作法以後可使用 攔截器了
二.源碼
看源碼 逆向思惟 -> 攔截器在哪裏執行的 -> 攔截器是哪裏來的
1.攔截在哪裏執行的
- 我看到網上有不少說攔截器的實現原理是動態代理,其實並非, aop的實現原理是動態代理
- 攔截器的實現原理是執行鏈 HandlerExecutionChain
- 這個過程是HandlerExecutionChain是spring-mvc(由於這個文章記錄的是攔截器,不會多說springmvc的東西) 中產生的.
執行代碼以下: org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)mvc
上面代碼中的標註
1,2,3:
- 根據handlerMapping獲取執行鏈HandlerExecutionChain(不一樣的請求映射關係是放在不懂的mapping中的,這裏不一樣的請求指的是不一樣的controller或者是資源請求,這塊是mvc的東西很少說了.),正常獲取的mpping爲requestMappingHandlerMapping
- 獲取HandlerExecutionChain以後標註2的執行代碼就是攔截器的執行
3.
標註3的執行代碼正常的請求,此處不詳解
2.攔截器從哪裏來的
執行時期
- 獲取全部的攔截器,發現攔截器是存放在 HandlerExecutionChain.interceptors中.
- HandlerExecutionChain 是在 org.springframework.web.servlet.DispatcherServlet.getHandler(HttpServletRequest)中返回的,說明HandlerExecutionChain.interceptors也是在這個時候別賦值的.
- DispatcherServlet.getHandler(HttpServletRequest)代碼以下:
AbstractHandlerMapping.getHandlerExecutionChain(Object, HttpServletRequest)app
說明
HandlerExecutionChain interceptors 是 從
AbstractHandlerMapping.adaptedInterceptors中拿得值
spring啓動時期
如今咱們知道了 執行的攔截器是從 AbstractHandlerMapping.adaptedInterceptors中拿到的
先看下AbstractHandlerMapping的結構,發現咱們上面說到的requestMappinghandlerMapping是它的子類,這個也就是咱們要講的重點(requestMappinghandlerMapping的實例化過程)學習
這個地方先說下我看這段源碼的思路
- 咱們須要探究的是AbstractHandlerMapping.interceptors.由於咱們getHandler中使用的是requestMappinghandlerMapping的實例.他們又是父子關係.因此interceptors是在requestMappingHandlerMapping實例化過程當中被添加進去的.
- 思路到了這個地方,要知道,一個實例spring建立的過程: 放入BeanDefinitionMap -> getBean()(這裏springIoc的源碼不說了,之後有時間在寫).
- 在getBean的執行地方debug 條件爲BeanName.equals("requestMappingHandlerMapping"),發現不是經過構造器建立的,是根據@bean建立的.
發現是在WebMvcConfigurationSupport.requestMappingHandlerMapping()
AbstractHandlerMapping.setInterceptors(Object...)
WebMvcConfigurationSupport.getInterceptors() spa
看了上面的代碼你會發現addInterceptors是被咱們重寫的
咱們把本身的攔截器傳給了這個方法.
總結:
攔截器是在springmvc處理請求的時候執行debug
是在執行鏈中存放的.3d
執行鏈中的 interceptors 是從AbstractHandlerMapping中拿到的.代理
AbstractHandlerMapping 中的 攔截器 是在 requestMappingHandlerMapping 初始化的過程存放的.
requestMappingHandlerMapping 初始化的時候 會調用 WebMvcConfigurationSupport 中的 addInterceptors()方法
這個方法被咱們重寫了,就是在使用 攔截器 的兩個步驟中的 第二步 ,咱們把本身寫的攔截器傳了進去