疑问:在mvc:interceptor 实际使用过程中,interceptor的执行顺序是依赖配置顺序吗,这样引出以下问题。
1、mvc:interceptor 配置怎样解析、初始化?
2、springmvc 处理请求的过程中,interceptors怎样工作的?
...
Insight结论:interceptor的执行顺序就在mvc:interceptor 配置解析时决定,依赖配置顺序。
...
Insight过程:
Insight spring源码,按照以往的分析,mvc:xxx配置的解析由MvcNamespaceHandler 完成。
1、配置解析,以下代码列出了mvc:interceptor解析以及注册到bean-factory的过程。
// 1.MvcNamespaceHandler 注册mvc:interceptor 解析器
registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
// 2.InterceptorsBeanDefinitionParser 解析Element 并构造MappedInterceptor
// 构造函数:MappedInterceptor(String[] includePatterns, String[] excludePatterns, HandlerInterceptor interceptor)
// 3.register this MappedInterceptor as Element 解析顺序
String beanName = parserContext.getReaderContext().registerWithGeneratedName(mappedInterceptorDef);
/**
* core! 参考DefaultListableBeanFactory 实现
* List of bean definition names, in registration order
*/
private final List
beanDefinitionNames = new ArrayList
(64);
2、interceptor 初始化(将bean-factory解析的MappedInterceptor 注入AbstractHandlerMapping)
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport {
private final List
mappedInterceptors = new ArrayList
();
/**
* Initializes the interceptors.
* @see ApplicationContextAwareProcessor.postProcessBeforeInitialization 调用该方法
*/
@Override
protected void initApplicationContext() throws BeansException {
extendInterceptors(this.interceptors);
detectMappedInterceptors(this.mappedInterceptors);
initInterceptors();
}
/**
* Detect beans of type MappedInterceptor and add them to the list of mapped interceptors.
* 该结果来源于bean-factory beanDefinitionNames 顺序仍然不变!
*/
protected void detectMappedInterceptors(List
mappedInterceptors) {
mappedInterceptors.addAll(
BeanFactoryUtils.beansOfTypeIncludingAncestors(getApplicationContext(), MappedInterceptor.class, true, false).values()
);
}
/**
* Look up a handler for the given request, falling back to the default
* handler if no specific one is found.
*/
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
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);
}
return getHandlerExecutionChain(handler, request);
}
/**
* Build a HandlerExecutionChain for the given handler, including
* applicable interceptors.
* The default implementation builds a standard HandlerExecutionChain
* with the given handler, the handler mapping's common interceptors, and any
* MappedInterceptors matching to the current request URL.
*/
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
chain.addInterceptors(getAdaptedInterceptors());
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
for (MappedInterceptor mappedInterceptor : this.mappedInterceptors) {
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
return chain;
}
}
...
3、interceptors 工作的过程:
参考上述的源码,遍历HandlerMapping.mappedInterceptors,根据request path匹配符合的拦截器。
也就是说:DispatcherServlet处理请求
getHandler per request
匹配拦截器 per request