經過前三章的分析,咱們簡要分析了SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping和RequestMappingHandlerMapping,但對攔截器部分作詳細的分析,攔截器的加載和初始化是三個HandlerMapping相同的部分。本節補充下這塊內容。跨域
本系列文章是基於Spring5.0.5RELEASE。mvc
類的繼承關係,以下圖:app
咱們知道Spring MVC將請求發送到Handler(Controller)處理器的功能是經過HandlerMapping組件完成的,HandlerMapping組件除了能找到Handler,還對攔截器進行了處理,具體實現是經過AbstractHandlerMapping抽象類完成的。ide
HandlerMapping接口只定義了一個方法getHandler,其做用是返回請求的處理鏈HandlerExecutionChain,該對象封裝了請求的攔截器以及請求處理Handler,方法定義以下:函數
@Nullable HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
類聲明源碼以下:源碼分析
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered { // ... ... }
從類的定義可知道,AbstractHandlerMapping抽象類繼承WebApplicationObjectSupport並實現了HandlerMapping和Ordered接口,其中:學習
簡言之,AbstractHandlerMapping類爲咱們提供上下文環境、初始化攔截器並封裝到HandlerExecutionChain對象中。this
該類的入口方法,源代碼以下:url
/** * 初始化攔截器 */ @Override protected void initApplicationContext() throws BeansException { // 提供給子類去重寫的,不過Spring並未去實現 extendInterceptors(this.interceptors); // 加載攔截器 detectMappedInterceptors(this.adaptedInterceptors); // 歸併攔截器 initInterceptors(); } /** * 空實現 */ protected void extendInterceptors(List<Object> interceptors) { } /** * 從上下文中加載MappedInterceptor類型的攔截器,好比咱們在配置文件中使用 * <mvc:interceptors></mvc:interceptors> * 標籤配置的攔截器 */ protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) { mappedInterceptors.addAll( BeanFactoryUtils.beansOfTypeIncludingAncestors( obtainApplicationContext(), MappedInterceptor.class, true, false).values()); } /** * 合併攔截器,即將<mvc:interceptors></mvc:interceptors>中的攔截器與HandlerMapping中經過屬性interceptors設置的攔截器進行合併 */ protected void initInterceptors() { if (!this.interceptors.isEmpty()) { for (int i = 0; i < this.interceptors.size(); i++) { Object interceptor = this.interceptors.get(i); if (interceptor == null) { throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null"); } // 適配後加入adaptedInterceptors this.adaptedInterceptors.add(adaptInterceptor(interceptor)); } } } /** * 適配HandlerInterceptor和WebRequestInterceptor */ protected HandlerInterceptor adaptInterceptor(Object interceptor) { if (interceptor instanceof HandlerInterceptor) { return (HandlerInterceptor) interceptor; } else if (interceptor instanceof WebRequestInterceptor) { return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor); } else { throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName()); } }
至此,攔截器初始化完成,接下來咱們分析getHandler方法,源碼以下:spa
/** * 返回請求處理的HandlerExecutionChain */ @Override @Nullable public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // getHandlerInternal()爲抽象方法,具體需子類實現 Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } // 將請求處理器封裝爲HandlerExectionChain HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); // 對跨域的處理 if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; } /** * 鉤子函數,需子類實現 */ @Nullable protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception; /** * 構建handler處理器的HandlerExecutionChain,包括攔截器 */ protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); // 迭代添加攔截器 for (HandlerInterceptor interceptor : this.adaptedInterceptors) { // 若是攔截器是MappedInterceptor,判斷是否對該handler進行攔截,是的狀況下添加 if (interceptor instanceof MappedInterceptor) { MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { // HandlerInterceptor直接添加,即經過HandingMapping屬性配置的攔截器 chain.addInterceptor(interceptor); } } return chain; }
本節咱們補充了攔截器的加載初始化過程以及getHandler方法的實現分析,但願對你們有所幫助。
最後建立了qq羣方便你們交流,可掃描加入,同時也可加我qq:276420284,共同窗習、共同進步,謝謝!