You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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对应的基础执行链需单独构建,再结合全局和路径匹配拦截器,无法提前缓存所有可能的执行链组合。

内存优化方案

针对重复正则匹配带来的内存问题,可通过以下方式优化:

  1. 开启路径匹配缓存:使用AntPathMatcher时,开启缓存避免重复解析正则表达式:
    @Bean
    public PathMatcher pathMatcher() {
        AntPathMatcher pathMatcher = new AntPathMatcher();
        pathMatcher.setCachePatterns(true);
        return pathMatcher;
    }
    
  2. 自定义拦截器匹配缓存:若使用自定义MappedInterceptor,可在内部实现匹配结果缓存,针对相同请求路径或属性复用匹配结果,减少重复计算。
  3. 升级Spring版本:Spring Boot 3.x及以上版本引入了更高效的PathPattern替代传统PathMatcher,优化了路径匹配逻辑和执行链构建流程,大幅降低正则匹配开销。
  4. 减少动态匹配拦截器数量:将无需动态匹配的拦截器改为全局拦截器,避免每次请求都执行匹配逻辑。

内容的提问来源于stack exchange,提问作者qijia wang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 08:37:36