今天将对SpringBoot中的拦截器interceptor从功能、实现、源码等方面进行分析。
何为拦截器
拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截,然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。
拦截器作用
日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等
权限检查:如登录检测,进入处理器检测检测是否登录
性能监控:通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间。(反向代理,如apache也可以自动记录);
通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现。
拦截器实现
通过实现HandlerInterceptor接口,并重写该接口的三个方法来实现拦截器的自定义。
接口 | 接口名称 | 说明 |
---|---|---|
preHandle | 前置处理 | 在实际的Handle执行前执行;有Boolean类型的返回值,如果返回为False,则Handle本身及postHandle/afterCompletion以及后续的拦截器全部都不会再继续执行;为True则反之。 |
postHandle | 后置处理 | Handle执行后视图渲染前执行 |
afterCompletion | 完成后处理 | Handle执行且视图渲染完成后执行 |
运行流程如下:
- 拦截器执行顺序是按照Spring配置文件中定义的顺序而定的。
- 会先按照顺序执行所有拦截器的preHandle方法,一直遇到return false为止,比如第二个preHandle方法是return false,则第三个以及以后所有拦截器都不会执行。若都是return true,则按顺序加载完preHandle方法。
- 然后执行主方法(自己的controller接口),若中间抛出异常,则跟return false效果一致,不会继续执行postHandle,只会倒序执行afterCompletion方法。
-
在主方法执行完业务逻辑(页面还未渲染数据)时,按倒序执行postHandle方法。若第三个拦截器的preHandle方法return false,则会执行第二个和第一个的postHandle方法和afterCompletion(postHandle都执行完才会执行这个,也就是页面渲染完数据后,执行after进行清理工作)方法。(postHandle和afterCompletion都是倒序执行)
一般实现拦截器都是继承HandlerInterceptorAdapter这个类。这个类是实现AsyncHandlerInterceptor接口的抽象类,而AsyncHandlerInterceptor又是继承HandlerInterceptor的接口,额外提供了afterConcurrentHandlingStarted方法,该方法是用来处理异步请求的。这个方法会在Controller方法异步执行时开始执行,而Interceptor的postHandle方法则是需要等到Controller的异步执行完才能执行。异步请求先支持preHandle、然后执行afterConcurrentHandlingStarted。异步线程完成之后执行preHandle、postHandle、afterCompletion。
这里来看一下HandlerInterceptorAdapter的源码:
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.handler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
* Abstract adapter class for the {@link AsyncHandlerInterceptor} interface,
* for simplified implementation of pre-only/post-only interceptors.
*
* @author Juergen Hoeller
* @since 05.12.2003
*/
public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {
/**
* This implementation always returns {@code true}.
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
/**
* This implementation is empty.
*/
@Override
public void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
}
/**
* This implementation is empty.
*/
@Override
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
/**
* This implementation is empty.
*/
@Override
public void afterConcurrentHandlingStarted(
HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
}
}
可见HandlerInterceptorAdapter它“empty”地实现了三个HandlerInterceptor的三个方法和AsyncHandlerInterceptor新增的处理异步方法。如果实现HandlerInterceptor接口的话,三个方法必须实现,不管需不需要,而HandlerInterceptorAdapter适配器,允许我们只实现需要的回调方法,这应该算是适配器设计模式的实现。
下面简单创建一个自定义的拦截器demo,继承HandlerInterceptorAdapter。
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("================================== preHandle1 ===========================================");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("================================== postHandle1 ===========================================");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("================================== afterCompletion1 ===========================================");
}
}
还需要创建一个配置类将该拦截器注入到spring容器中,这个配置类要实现WebMvcConfigurer。
(注意:继承WebMvcConfigurerAdapter类这种方式官方建议废弃)
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor());
}
}
HandlerInterceptor源码
直接上翻译后的源码:
/**
* preHandle方法是进行处理器拦截用的,顾名思义,该方法将在Controller处理之前进行调用,SpringMVC中的Interceptor拦截器是链式的,可以同时存在
* 多个Interceptor,然后SpringMVC会根据声明的前后顺序一个接一个的执行,而且所有的Interceptor中的preHandle方法都会在
* Controller方法调用之前调用。SpringMVC的这种Interceptor链式结构也是可以进行中断的,这种中断方式是令preHandle的返
* 回值为false,当preHandle的返回值为false的时候整个请求就结束了。
*/
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception;
/**
* 这个方法只会在当前这个Interceptor的preHandle方法返回值为true的时候才会执行。postHandle是进行处理器拦截用的,它的执行时间是在处理器进行处理之
* 后,也就是在Controller的方法调用之后执行,但是它会在DispatcherServlet进行视图的渲染之前执行,也就是说在这个方法中你可以对ModelAndView进行操
* 作。这个方法的链式结构跟正常访问的方向是相反的,也就是说先声明的Interceptor拦截器该方法反而会后调用,这跟Struts2里面的拦截器的执行过程有点像,
* 只是Struts2里面的intercept方法中要手动的调用ActionInvocation的invoke方法,Struts2中调用ActionInvocation的invoke方法就是调用下一个Interceptor
* 或者是调用action,然后要在Interceptor之前调用的内容都写在调用invoke之前,要在Interceptor之后调用的内容都写在调用invoke方法之后。
*/
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception;
/**
* 该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。该方法将在整个请求完成之后,也就是DispatcherServlet渲染了视图执行,
* 这个方法的主要作用是用于清理资源的,当然这个方法也只能在当前这个Interceptor的preHandle方法的返回值为true时才会执行。
*/
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception;
}
每一个拦截器都有一个preHandle()方法和postHandle()方法。在调用处理器之前后,都会调用拦截器。由许多个拦截器组成一个执行链,而这个执行链是以数组的形式存在。所以,执行这个执行链的中的所有拦截器的preHandle()方法是按照interceptor[]数组的正序执行的,也就是按数组下标从小到大执行每一个拦截器的preHandle()方法。而拦截器的postHandle()方法的执行是按照逆序执行的,也就是按照interceptor[]数组的下标从大到小的顺序执行拦截器中的postHandle()方法。而拦截器中的每一个afterCompletion()方法都是在渲染完视图以后按照interceptor[]数组的下标从大到小的顺序执行拦截器中的afterCompletion()方法,也就是说afterCompletion()方法的执行顺序跟postHandle()方法的执行顺序是一样的。如下图:
当然这是正常情况下的执行顺序,但是当某一个拦截器的preHandle()方法()返回false,那么handler(处理器就不会执行)。它会直接去掉用当前拦截器的前一个拦截器的afterCompletion()方法,从这个方法开始逆序执行。比如:这里的interceptor3的preHandle()方法返回false。那么就会直接调用interceptor2的afterCompletion()方法,并从这个方法开始逆序执行至结束。
HandlerInterceptor实现原理
下面结合SpringMVC来看一下拦截器的内部实现。源码上关键地方均加了注释。
首先,我们看一下 org.springframework.web.servlet.DispatcherServlet
中doDispatch方法,在这里可见执行顺序:preHandle->controller对应的方法->postHandle->afterCompletion->afterConcurrentHandlingStarted。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
//调用已注册HandlerInterceptor的preHandle()方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 真正执行Controller对应的方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
//调用已注册HandlerInterceptor的postHandle()方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
//调用已注册HandlerInterceptor的afterCompletion()方法
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
//调用已注册HandlerInterceptor的afterCompletion()方法
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
//调用已注册HandlerInterceptor的afterConcurrentHandlingStarted()方法
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
/**
* Handle the result of handler selection and handler invocation, which is
* either a ModelAndView or an Exception to be resolved to a ModelAndView.
*/
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
boolean errorView = false;
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
"': assuming HandlerAdapter completed request handling");
}
}
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}
if (mappedHandler != null) {
//调用已注册HandlerInterceptor的afterCompletion()方法
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
接下来看看 HandlerExecutionChain的applyPreHandle方法实现:
/**
* 执行注册到该请求上的所有HandlerInterceptor的 preHandle 方法
*/
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
public HandlerInterceptor[] getInterceptors() {
if (this.interceptors == null && this.interceptorList != null) {
this.interceptors = this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);
}
return this.interceptors;
}
HandlerExecutionChain的applyPostHandle方法实现:
* 执行注册到该请求上的所有HandlerInterceptor的 postHandle 方法
*/
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
HandlerExecutionChain的triggerAfterCompletion方法实现:
* 执行注册到该请求上的所有HandlerInterceptor的 afterCompletion 方法
*/
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
最后,HandlerExecutionChain的applyAfterConcurrentHandlingStarted方法实现:
/**
* 执行注册到该请求上的所有AsyncHandlerInterceptor的 afterConcurrentHandlingStarted 方法
*/
void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
if (interceptors[i] instanceof AsyncHandlerInterceptor) {
try {
AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) interceptors[i];
asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler);
}
catch (Throwable ex) {
logger.error("Interceptor [" + interceptors[i] + "] failed in afterConcurrentHandlingStarted", ex);
}
}
}
}
}
接下来,HandlerExecutionChain 内部的Interceptor数组是在什么时候初始化的呢?
来看看 HandlerExecutionChain 类的定义,源码如下:
package org.springframework.web.servlet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
public class HandlerExecutionChain {
private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
private final Object handler;
private HandlerInterceptor[] interceptors;
private List interceptorList;
private int interceptorIndex = -1;
public HandlerExecutionChain(Object handler) {
this(handler, (HandlerInterceptor[]) null);
}
public HandlerExecutionChain(Object handler, HandlerInterceptor... interceptors) {
if (handler instanceof HandlerExecutionChain) {
HandlerExecutionChain originalChain = (HandlerExecutionChain) handler;
this.handler = originalChain.getHandler();
this.interceptorList = new ArrayList();
CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);
CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);
}
else {
this.handler = handler;
this.interceptors = interceptors;
}
}
/**
* 向handler中添加interceptor
*/
public void addInterceptor(HandlerInterceptor interceptor) {
initInterceptorList().add(interceptor);
}
/**
* 向handler中添加多个interceptor
*/
public void addInterceptors(HandlerInterceptor... interceptors) {
if (!ObjectUtils.isEmpty(interceptors)) {
initInterceptorList().addAll(Arrays.asList(interceptors));
}
}
private List initInterceptorList() {
if (this.interceptorList == null) {
this.interceptorList = new ArrayList();
if (this.interceptors != null) {
// An interceptor array specified through the constructor
this.interceptorList.addAll(Arrays.asList(this.interceptors));
}
}
this.interceptors = null;
return this.interceptorList;
}
/**
* 按顺序返回handler上的HandlerInterceptor列表
*/
public HandlerInterceptor[] getInterceptors() {
if (this.interceptors == null && this.interceptorList != null) {
this.interceptors = this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);
}
return this.interceptors;
}
}
HandlerExecutionChain 提供了addInterceptors()方法来添加HandlerInterceptor,那addInterceptors是在哪里被调用的呢?
回到DispatcherServlet 的 doDispatch方法中,如下:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 获取当前请求对应的handler
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
...
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
...
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
...
}
}
/**
* 获取当前请求对应的HandlerExecutionChain
*/
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
接着来看看HandlerMapping 的getHandler(request)方法,HandlerMapping是一个接口,getHandler(request)方法是在AbstractHandlerMapping中实现的,如下:
@Override
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//获取请求对应的handler
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 = getApplicationContext().getBean(handlerName);
}
//根据handler构造HandlerExecutionChain
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
/**
* 构造HandlerExecutionChain, 并初始化HandlerInterceptor
*/
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) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
可见,在这里调用了addInterceptor,构造HandlerExecutionChain并初始化HandlerInterceptor。
该方法就是从adaptedInterceptors属性中,根据URL查找添加条件的Interceptor并组装成HandlerExecutionChain并返回。
此处是否满足条件的判断是根据添加拦截器配置时调用的addPathPatterns方法决定的。
那么,要是还想继续深究下去的话:
现在的问题就是adaptedInterceptors属性是如何初始化的。
通过分析AbstractHandlerMapping类,其adaptedInterceptors属性实际是在initInterceptors方法中根据interceptors来进行初始化的。现在的问题转变成interceptors这个属性是如何初始化的了。 实际上这个属性是通过setInterceptors方法来设置的,但通过Alt+F7的搜索并未搜索到该方法是在哪个地方调用的。
我们换个思路,通过@EnableWebMvc来分析看通过addInterceptors方法配置的Interceptor在到底添加到哪去了。
前言已经分析,通过@EnableWebMvc注解实际上引入了DelegatingWebMvcConfiguration这个类;查看这个类,在其中有一方法被Autowired注解:
public void setConfigurers(List configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.configurers.addWebMvcConfigurers(configurers);
}
}
通过查看Autowired注解定义,了解到当它使用在List参数的方法上时,会查找List所包含的对象类型的所有Bean然后进行注入。这也意味着,此处会将所有实现WebMvcConfigurer接口的类进行注入,然后添加到configurers属性中去;在此处,我们自定义的继承自WebMvcConfigurer的类会被注入。
再查看 DelegatingWebMvcConfiguration 这个类,它继承了 WebMvcConfigurationSupport 类。分析WebMvcConfigurationSupport,可以看到以下方法:
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
mapping.setOrder(0);
mapping.setInterceptors(getInterceptors());
mapping.setContentNegotiationManager(mvcContentNegotiationManager());
mapping.setCorsConfigurations(getCorsConfigurations());
PathMatchConfigurer configurer = getPathMatchConfigurer();
Boolean useSuffixPatternMatch = configurer.isUseSuffixPatternMatch();
Boolean useRegisteredSuffixPatternMatch = configurer.isUseRegisteredSuffixPatternMatch();
Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch();
if (useSuffixPatternMatch != null) {
mapping.setUseSuffixPatternMatch(useSuffixPatternMatch);
}
if (useRegisteredSuffixPatternMatch != null) {
mapping.setUseRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch);
}
if (useTrailingSlashMatch != null) {
mapping.setUseTrailingSlashMatch(useTrailingSlashMatch);
}
UrlPathHelper pathHelper = configurer.getUrlPathHelper();
if (pathHelper != null) {
mapping.setUrlPathHelper(pathHelper);
}
PathMatcher pathMatcher = configurer.getPathMatcher();
if (pathMatcher != null) {
mapping.setPathMatcher(pathMatcher);
}
return mapping;
}
可以看到RequestMappingHandlerMapping类被注入Spring容器。
同时通过mapping.setInterceptors(getInterceptors())将所有的Interceptors设置到HandperMapping对象中 。
这样就找到了ReuqestMappingHandlerMapping的setInterceptors方法调用处了。
接下来的问题就是此处调用的getInterceptors方法的实现:
if (this.interceptors == null) {
InterceptorRegistry registry = new InterceptorRegistry();
addInterceptors(registry);
registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService()));
registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider()));
this.interceptors = registry.getInterceptors();
}
return this.interceptors.toArray();
}
此处如果interceptors对象为空时,会调用addInterceptors方法;其实现在DelegatingWebMvcConfiguration类中:
protected void addInterceptors(InterceptorRegistry registry) {
this.configurers.addInterceptors(registry);
}
在前文已经描述到,DelegatingWebMvcConfiguration类中的configurers属性会将所有继承了WebMvcConfigurer的配置类全部添加进去。如我们自定义的配置类;在此处调用DelegatingWebMvcConfiguration的addInterceptors方法时,实际就是调用各个WebMvcConfigurer对象的addInterceptors方法来完成自定义的Interceptor注册过程。
通过这一系列过程,RequestMappingHandlerMapping的getInterceptors方法就可以获取到所有自定义的Interceptor了。
完事!
注:
实现原理部分参考结合了https://www.jianshu.com/p/b849f9919130和https://blog.csdn.net/icarusliu/article/details/78833520,两位作者正好各分析了上半段和下半段的源码。