Spring MVC为何为每个请求重复获取HandlerExecutionChain?性能问题解析
为什么Spring MVC会为每个请求重复获取HandlerExecutionChain?
问题背景
每次请求时创建新的HandlerExecutionChain会导致正则匹配逻辑重复执行,进而造成内存过度分配。使用的Spring Boot Web版本为2.7.0。
相关核心代码如下:
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { HandlerExecutionChain chain = handler instanceof HandlerExecutionChain ? (HandlerExecutionChain)handler : new HandlerExecutionChain(handler); Iterator var4 = this.adaptedInterceptors.iterator(); while(var4.hasNext()) { HandlerInterceptor interceptor = (HandlerInterceptor)var4.next(); if (interceptor instanceof MappedInterceptor) { MappedInterceptor mappedInterceptor = (MappedInterceptor)interceptor; if (mappedInterceptor.matches(request)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { chain.addInterceptor(interceptor); } } return chain; } public boolean match(Object path, boolean isPathContainer, PathMatcher pathMatcher) { if (isPathContainer) { PathContainer pathContainer = (PathContainer)path; if (this.pathPattern != null) { return this.pathPattern.matches(pathContainer); } String lookupPath = pathContainer.value(); path = UrlPathHelper.defaultInstance.removeSemicolonContent(lookupPath); } return pathMatcher.match(this.patternString, (String)path); }
内存分配火焰图显示:正则匹配逻辑的重复执行是内存过度分配的主要来源。
原因分析
Spring MVC为每个请求重新构建HandlerExecutionChain,核心原因有三点:
- 拦截器匹配的动态性:
MappedInterceptor的匹配规则依赖请求实时属性(如路径、参数、Header等),无法提前确定哪些拦截器需要加入执行链。比如部分拦截器仅对特定路径、请求方法生效,这些判断必须基于当前请求上下文完成。 - 线程安全保障:HandlerExecutionChain包含拦截器实例,若复用同一实例,多线程环境下会出现并发修改问题(不同请求添加不同拦截器),因此必须为每个请求创建独立实例保证线程安全。
- Handler的多样性:不同请求可能匹配不同的控制器方法(Handler),每个Handler对应的基础执行链需单独构建,再结合全局和路径匹配拦截器,无法提前缓存所有可能的执行链组合。
内存优化方案
针对重复正则匹配带来的内存问题,可通过以下方式优化:
- 开启路径匹配缓存:使用
AntPathMatcher时,开启缓存避免重复解析正则表达式:@Bean public PathMatcher pathMatcher() { AntPathMatcher pathMatcher = new AntPathMatcher(); pathMatcher.setCachePatterns(true); return pathMatcher; } - 自定义拦截器匹配缓存:若使用自定义
MappedInterceptor,可在内部实现匹配结果缓存,针对相同请求路径或属性复用匹配结果,减少重复计算。 - 升级Spring版本:Spring Boot 3.x及以上版本引入了更高效的
PathPattern替代传统PathMatcher,优化了路径匹配逻辑和执行链构建流程,大幅降低正则匹配开销。 - 减少动态匹配拦截器数量:将无需动态匹配的拦截器改为全局拦截器,避免每次请求都执行匹配逻辑。
内容的提问来源于stack exchange,提问作者qijia wang
相关产品推荐
相关产品推荐

