
目录第一部分启动阶段 —— 拦截器的配置、收集、包装与存储第 1 章DelegatingWebMvcConfiguration 的由来 —— 它是如何被 Spring 管理的1.1 纯 Spring MVC 项目通过 EnableWebMvc 的 Import 机制1.2 Spring Boot 项目通过自动配置引入1.3 DelegatingWebMvcConfiguration 的继承结构第 2 章Autowired 收集所有 WebMvcConfigurer第 3 章WebMvcConfigurationSupport 中的 Bean 定义 —— RequestMappingHandlerMapping 的创建第 4 章getInterceptors() 的内部执行流程第 5 章registry.getInterceptors() —— 生成 MappedInterceptor[] 数组第 6 章RequestMappingHandlerMapping 的 Bean 生命周期 —— initInterceptors() 的执行第二部分运行阶段 —— 请求到来时拦截器的匹配与执行第 7 章DispatcherServlet.doDispatch() —— 拦截器链的构建入口第 8 章getHandlerExecutionChain() —— 拦截器匹配逻辑第 9 章MappedInterceptor.matches() —— 路径匹配的核心算法第 10 章拦截器链的执行 —— HandlerExecutionChain 的三个调用点第三部分总结第 11 章完整时序图第 12 章核心设计思想第 13 章关键源码位置速查第一部分启动阶段 —— 拦截器的配置、收集、包装与存储第 1 章DelegatingWebMvcConfiguration的由来 —— 它是如何被 Spring 管理的DelegatingWebMvcConfiguration是 Spring MVC 中连接“核心配置”与“用户扩展”的总枢纽。它被 Spring 管理的方式有两种取决于你的项目类型。1.1 纯 Spring MVC 项目通过EnableWebMvc的Import机制在非 Spring Boot 项目中你需要显式添加EnableWebMvc注解。查看该注解的源码Retention(RetentionPolicy.RUNTIME)Target(ElementType.TYPE)DocumentedImport(DelegatingWebMvcConfiguration.class)publicinterfaceEnableWebMvc{}Import(DelegatingWebMvcConfiguration.class)会直接将DelegatingWebMvcConfiguration注册为 Spring 容器的一个 Bean。这是 Spring 注解驱动的核心机制——Import可以导入一个配置类使其所有Bean方法生效。1.2 Spring Boot 项目通过自动配置引入在 Spring Boot 项目中你无需手动加EnableWebMvc。WebMvcAutoConfiguration是 Spring Boot 的 MVC 自动配置类它内部通过Import(EnableWebMvcConfiguration.class)引入了一个配置类该类直接继承了DelegatingWebMvcConfiguration。由于WebMvcAutoConfiguration本身是自动配置类被 Spring Boot 自动加载因此DelegatingWebMvcConfiguration的子类也自然成为 Spring 容器中的 Bean。1.3DelegatingWebMvcConfiguration的继承结构DelegatingWebMvcConfiguration继承自WebMvcConfigurationSupport后者提供了 Spring MVC 所有核心基础设施的Bean定义如RequestMappingHandlerMapping、HandlerAdapter、ViewResolver等。DelegatingWebMvcConfiguration在其中扮演了“委托”的角色——它不直接实现配置逻辑而是将所有配置调用转发给一个组合对象而这个组合对象会收集所有WebMvcConfigurer的实现。第 2 章Autowired收集所有WebMvcConfigurerDelegatingWebMvcConfiguration中有一个关键方法Autowired(requiredfalse)publicvoidsetConfigurers(ListWebMvcConfigurerconfigurers){if(!CollectionUtils.isEmpty(configurers)){this.configurers.addWebMvcConfigurers(configurers);}}Autowired(required false)告诉 Spring如果有任何WebMvcConfigurer类型的 Bean请全部注入到这里。ListWebMvcConfigurer会包含你写的WebConfig类以及任何第三方库如 Spring Security提供的配置类。这些配置被传递给WebMvcConfigurerComposite的addWebMvcConfigurers方法存入其内部的delegates列表。WebMvcConfigurerComposite是一个组合模式的实现它实现了WebMvcConfigurer接口内部维护一个ListWebMvcConfigurer delegates。后续所有配置方法被调用时它都会遍历delegates依次调用每个配置类的对应方法。这保证了多个配置类可以并存且按照添加顺序依次生效。第 3 章WebMvcConfigurationSupport中的Bean定义 ——RequestMappingHandlerMapping的创建WebMvcConfigurationSupport中有一个关键的Bean方法BeanpublicRequestMappingHandlerMappingrequestMappingHandlerMapping(Qualifier(mvcContentNegotiationManager)ContentNegotiationManagercontentNegotiationManager,Qualifier(mvcConversionService)FormattingConversionServiceconversionService,Qualifier(mvcResourceUrlProvider)ResourceUrlProviderresourceUrlProvider){RequestMappingHandlerMappingmappingcreateRequestMappingHandlerMapping();mapping.setOrder(0);// 【核心】这一行触发了拦截器配置的收集和包装mapping.setInterceptors(getInterceptors(conversionService,resourceUrlProvider));mapping.setContentNegotiationManager(contentNegotiationManager);// ... 其他配置returnmapping;}mapping.setInterceptors(getInterceptors(...))是整条链路的触发点。它调用了getInterceptors()方法这个方法会执行以下操作创建一个InterceptorRegistry实例。调用addInterceptors(registry)这是一个由子类DelegatingWebMvcConfiguration重写的方法。调用registry.getInterceptors()将注册信息转换为Object[]数组其中包含MappedInterceptor和普通拦截器。将这个数组设置给HandlerMapping实例。第 4 章getInterceptors()的内部执行流程WebMvcConfigurationSupport.getInterceptors()的完整源码如下protectedfinalObject[]getInterceptors(FormattingConversionServicemvcConversionService,ResourceUrlProvidermvcResourceUrlProvider){if(this.interceptorsnull){InterceptorRegistryregistrynewInterceptorRegistry();// 【多态调用】实际执行的是 DelegatingWebMvcConfiguration.addInterceptorsaddInterceptors(registry);// 【关键转换】将注册信息转换为 MappedInterceptor 数组this.interceptorsregistry.getInterceptors();}returnthis.interceptors.toArray();}addInterceptors(registry)在父类WebMvcConfigurationSupport中是空实现但DelegatingWebMvcConfiguration重写了它// DelegatingWebMvcConfiguration.javaOverrideprotectedvoidaddInterceptors(InterceptorRegistryregistry){this.configurers.addInterceptors(registry);}this.configurers是WebMvcConfigurerComposite实例它的addInterceptors方法遍历delegates列表OverridepublicvoidaddInterceptors(InterceptorRegistryregistry){for(WebMvcConfigurerdelegate:this.delegates){delegate.addInterceptors(registry);// 调用你自己写的 WebConfig.addInterceptors}}在你的WebConfig中你调用了registry.addInterceptor(new LoginInterceptor()).addPathPatterns(/admin/**)。这一步将拦截器实例和路径规则存入InterceptorRegistry内部的InterceptorRegistration对象中。第 5 章registry.getInterceptors()—— 生成MappedInterceptor[]数组InterceptorRegistry.getInterceptors()的源码publicObject[]getInterceptors(){ListObjectinterceptorsnewArrayList();for(InterceptorRegistrationregistration:this.registrations){interceptors.add(registration.getInterceptor());}returninterceptors.toArray();}InterceptorRegistration.getInterceptor()的核心逻辑protectedObjectgetInterceptor(){if(this.includePatterns.isEmpty()this.excludePatterns.isEmpty()){returnthis.interceptor;// 没有路径规则直接返回原始拦截器}// 有路径规则包装成 MappedInterceptorreturnnewMappedInterceptor(this.includePatterns,this.excludePatterns,this.interceptor);}MappedInterceptor是一个包装类它同时持有拦截器实例和路径匹配规则includePatterns和excludePatterns用于运行时判断当前请求是否应该应用该拦截器。最终getInterceptors()返回的数组中包含了你配置的所有拦截器无路径规则的为原始拦截器有路径规则的为MappedInterceptor并通过mapping.setInterceptors()设置给了RequestMappingHandlerMapping实例。第 6 章RequestMappingHandlerMapping的 Bean 生命周期 ——initInterceptors()的执行RequestMappingHandlerMapping的继承链中存在关键接口ApplicationContextAware。当一个 Bean 实现了ApplicationContextAwareSpring 容器在初始化该 Bean 时会回调其setApplicationContext方法。AbstractHandlerMapping的父类ApplicationObjectSupport实现了ApplicationContextAware接口并重写了setApplicationContextOverridepublicfinalvoidsetApplicationContext(ApplicationContextcontext)throwsBeansException{// ...initApplicationContext();// 模板方法}AbstractHandlerMapping重写了initApplicationContext()OverrideprotectedvoidinitApplicationContext()throwsBeansException{extendInterceptors(this.interceptors);detectMappedInterceptors(this.adaptedInterceptors);initInterceptors();// 【最终执行】}initInterceptors()的源码protectedvoidinitInterceptors(){if(!ObjectUtils.isEmpty(this.interceptors)){for(Objectinterceptor:this.interceptors){if(interceptorinstanceofMappedInterceptor){// 带路径规则的存入 mappedInterceptorsthis.mappedInterceptors.add((MappedInterceptor)interceptor);}else{// 普通拦截器适配后存入 adaptedInterceptorsthis.adaptedInterceptors.add(adaptInterceptor(interceptor));}}}}interceptors数组是在第 3 章中通过setInterceptors设置进来的。分类后mappedInterceptors存放所有带路径规则的拦截器adaptedInterceptors存放普通拦截器对所有请求生效。至此启动阶段结束。内存状态AbstractHandlerMapping中已有mappedInterceptors和adaptedInterceptors两个集合等待请求到来时被使用。第二部分运行阶段 —— 请求到来时拦截器的匹配与执行第 7 章DispatcherServlet.doDispatch()—— 拦截器链的构建入口在doDispatch()中首先调用getHandler(processedRequest)获取HandlerExecutionChainmappedHandlergetHandler(processedRequest);getHandler()遍历所有HandlerMapping最终进入AbstractHandlerMapping.getHandler()它内部调用getHandlerExecutionChain(handler, request)来构建执行链。第 8 章getHandlerExecutionChain()—— 拦截器匹配逻辑protectedHandlerExecutionChaingetHandlerExecutionChain(Objecthandler,HttpServletRequestrequest){HandlerExecutionChainchain(handlerinstanceofHandlerExecutionChain)?(HandlerExecutionChain)handler:newHandlerExecutionChain(handler);// 遍历 adaptedInterceptors普通拦截器直接加入for(HandlerInterceptorinterceptor:this.adaptedInterceptors){chain.addInterceptor(interceptor);}// 遍历 mappedInterceptors带路径规则的需要匹配for(HandlerInterceptorinterceptor:this.mappedInterceptors){if(interceptorinstanceofMappedInterceptor){MappedInterceptormappedInterceptor(MappedInterceptor)interceptor;if(mappedInterceptor.matches(request)){chain.addInterceptor(mappedInterceptor.getInterceptor());}}}returnchain;}首先所有普通拦截器无路径规则无条件加入执行链。然后对每个MappedInterceptor调用matches(request)判断当前请求是否匹配其路径规则。若匹配则将其内部的拦截器实例加入执行链。第 9 章MappedInterceptor.matches()—— 路径匹配的核心算法publicbooleanmatches(HttpServletRequestrequest){// 1. 获取请求路径StringlookupPaththis.urlPathHelper.getLookupPathForRequest(request);// 2. 优先检查排除规则if(this.excludePatterns!null){for(Stringpattern:this.excludePatterns){if(this.pathMatcher.match(pattern,lookupPath)){returnfalse;// 命中排除规则不生效}}}// 3. 检查包含规则if(this.includePatternsnull){returntrue;// 没有包含规则默认对所有请求生效}for(Stringpattern:this.includePatterns){if(this.pathMatcher.match(pattern,lookupPath)){returntrue;// 命中包含规则生效}}returnfalse;// 没有命中任何包含规则不生效}urlPathHelper.getLookupPathForRequest(request)获取请求路径例如/admin/user。excludePatterns优先判断如果路径匹配任意排除规则直接返回false。includePatterns判断如果没有配置包含规则默认匹配所有请求否则必须匹配至少一个包含规则才返回true。pathMatcher默认是AntPathMatcher支持*单层、**多层、?单个字符等通配符。第 10 章拦截器链的执行 ——HandlerExecutionChain的三个调用点HandlerExecutionChain构建完成后doDispatch在三个不同时机调用其方法。10.1applyPreHandle()—— Controller 执行前if(!mappedHandler.applyPreHandle(processedRequest,response)){return;// 任意拦截器返回 false请求中断}applyPreHandle按正序执行所有拦截器的preHandle方法一旦某个返回false立即触发已执行拦截器的afterCompletion并返回false后续代码不再执行。10.2applyPostHandle()—— Controller 执行后视图渲染前mappedHandler.applyPostHandle(processedRequest,response,mv);逆序执行所有拦截器的postHandle方法。10.3triggerAfterCompletion()—— 视图渲染后或异常时mappedHandler.triggerAfterCompletion(processedRequest,response,null);在processDispatchResult的finally块中调用逆序执行所有拦截器的afterCompletion保证资源释放。10.4interceptorIndex的作用HandlerExecutionChain内部维护interceptorIndex记录当前执行到哪个拦截器。当preHandle失败回滚时只对interceptorIndex之前的拦截器执行afterCompletion避免未初始化的拦截器被误调用。第三部分总结第 11 章完整时序图启动阶段Spring 容器启动 ↓ DelegatingWebMvcConfiguration 被 Spring 管理通过 Import 或 Boot 自动配置 ↓ Autowired setConfigurers(ListWebMvcConfigurer) 收集所有 WebMvcConfigurer ↓ 存入 WebMvcConfigurerComposite.delegates ↓ WebMvcConfigurationSupport Bean 创建 RequestMappingHandlerMapping ↓ mapping.setInterceptors(getInterceptors(...)) ↓ getInterceptors() 创建 InterceptorRegistry调用 addInterceptors(registry) ↓ addInterceptors(registry) 多态 → DelegatingWebMvcConfiguration.addInterceptors ↓ WebMvcConfigurerComposite.addInterceptors → 遍历 delegates ↓ 你的 WebConfig.addInterceptors(registry) 执行 → 拦截器注册到 InterceptorRegistry ↓ registry.getInterceptors() → 生成 MappedInterceptor[] 数组 ↓ mapping.setInterceptors(interceptors) 存储到 AbstractHandlerMapping.interceptors ↓ Bean 初始化 → ApplicationContextAware.setApplicationContext 回调 ↓ AbstractHandlerMapping.initApplicationContext() → initInterceptors() ↓ 分类存储MappedInterceptor → mappedInterceptors普通 → adaptedInterceptors运行阶段请求到来 → DispatcherServlet.doDispatch() ↓ getHandler(processedRequest) → AbstractHandlerMapping.getHandler() ↓ getHandlerExecutionChain(handler, request) ├── adaptedInterceptors 全部加入 └── 遍历 mappedInterceptors ↓ MappedInterceptor.matches(request) 判断路径 ├── 匹配 excludePatterns → 跳过 ├── 未配置 includePatterns → 加入 └── 匹配 includePatterns → 加入 ↓ applyPreHandle() → 正序执行 preHandle失败则中断并回滚 ↓ ha.handle() → 执行 Controller ↓ applyPostHandle() → 逆序执行 postHandle ↓ processDispatchResult() → 视图渲染 / JSON 输出 ↓ triggerAfterCompletion() → 逆序执行 afterCompletion第 12 章核心设计思想设计思想体现组合模式WebMvcConfigurerComposite聚合多个WebMvcConfigurer配置统一调用委托模式DelegatingWebMvcConfiguration不自行处理全部委托给configurers模板方法模式ApplicationObjectSupport定义setApplicationContext流程子类实现initApplicationContext策略模式MappedInterceptor封装路径匹配策略运行时根据matches()决定是否生效接口隔离用户通过实现WebMvcConfigurer接口即可完成配置无需继承复杂基类第 13 章关键源码位置速查功能点类名方法名收集配置DelegatingWebMvcConfigurationsetConfigurers存储配置WebMvcConfigurerCompositeaddWebMvcConfigurers创建 HandlerMappingWebMvcConfigurationSupportrequestMappingHandlerMapping触发拦截器收集WebMvcConfigurationSupportgetInterceptors委托 addInterceptorsDelegatingWebMvcConfigurationaddInterceptors遍历配置WebMvcConfigurerCompositeaddInterceptors生成 MappedInterceptorInterceptorRegistrygetInterceptors包装拦截器InterceptorRegistrationgetInterceptor分类存储AbstractHandlerMappinginitInterceptors构建执行链AbstractHandlerMappinggetHandlerExecutionChain路径匹配MappedInterceptormatches执行拦截器HandlerExecutionChainapplyPreHandle、applyPostHandle、triggerAfterCompletion