← 返回题目列表

Filter、Interceptor、AOP 有什么区别?执行顺序是怎样的?

高频 中等 第 8 / 30 题 更新于 2026/07/26
FilterInterceptorAOP执行顺序

简化版

三者都能「在请求处理前后插入逻辑」,但层次和范围不同Filter(过滤器) 是 Servlet 规范的,最外层,拦截所有进入容器的请求(包括静态资源),由 Servlet 容器(Tomcat)管理;Interceptor(拦截器) 是 Spring MVC 的,在 DispatcherServlet 之后、Controller 之前拦截,只拦 SpringMVC 处理的请求,能拿到 Handler 信息;AOP 最内层,作用于任意 Bean 的方法(不限于 Controller),基于动态代理,粒度最细。执行顺序(由外到内):Filter → Interceptor → AOP → Controller 方法 → AOP → Interceptor → Filter,像剥洋葱一样进去再出来。

详细版

三者对比

维度FilterInterceptorAOP
规范/来源Servlet 规范Spring MVCSpring AOP
管理者Servlet 容器(Tomcat)Spring 容器Spring 容器
拦截范围所有请求(含静态资源、其他 Servlet)只拦 DispatcherServlet 处理的请求任意 Spring Bean 的方法
能否拿到 Handler否(只有 Request/Response)能(能拿到目标 Controller 方法)能(能拿到方法、参数、返回值)
底层原理函数回调(FilterChain)Spring MVC 拦截器链动态代理(JDK/CGLIB)
粒度最粗(请求级)中(Handler 级)最细(方法级)

执行顺序(洋葱模型)

请求进来 →
  Filter.doFilter(前)
    Interceptor.preHandle
      AOP(前置增强)
        Controller 方法执行
      AOP(后置增强)
    Interceptor.postHandle → afterCompletion
  Filter.doFilter(后)
→ 响应返回

顺序:外层先进后出(Filter 最外),像剥洋葱:进的时候由外到内,出的时候由内到外

Interceptor 的三个方法

public class MyInterceptor implements HandlerInterceptor {
    public boolean preHandle(...)  { return true; }  // Controller 前,返回 false 则中断
    public void postHandle(...)    { }               // Controller 后、视图渲染前
    public void afterCompletion(...) { }             // 视图渲染后(无论成功失败都执行,用于清理)
}

⚠️ Filter 和 Interceptor 都能拦截请求,但关键区别是「能不能拿到 Spring 的东西」:Filter 由 Servlet 容器管理,早于 Spring MVC,拿不到 Handler、Controller 方法信息,也不方便用 Spring 的 Bean(虽然现在也能注入);Interceptor 由 Spring 管理,能拿到目标 Handler、能方便用 Spring 容器的 Bean。所以「和业务/Handler 相关的拦截逻辑用 Interceptor,纯请求级的(编码、跨域、鉴权前置)用 Filter」。

完整版教学

一、三者的层次:一个请求经过的三道关卡

理解三者,先看一个请求从进入服务器到执行业务方法,要穿过哪几层:

浏览器请求

  ▼  ① Servlet 容器(Tomcat)层 —— Filter 在这里拦截(最外层)
  │      Filter 能拦所有请求,包括静态资源、任意 Servlet
  ▼  ② DispatcherServlet(Spring MVC 入口)

  ▼  ③ Spring MVC 层 —— Interceptor 在这里拦截
  │      只拦 DispatcherServlet 分发的请求,能拿到目标 Controller
  ▼  ④ Controller 方法

  ▼  ⑤ Service/任意 Bean 方法 —— AOP 在这里增强(最内层)
         AOP 作用于任意 Bean 方法,粒度最细

关键认知:三者是「由外到内」的三层拦截,范围逐层缩小、粒度逐层变细。Filter 最外、管所有请求;Interceptor 居中、只管 SpringMVC 请求;AOP 最内、管任意方法。这个「层次」决定了它们各自的能力和适用场景——越往外越通用但拿不到细节,越往里越能拿到方法细节但只在 Spring 内部。

二、Filter:Servlet 规范的最外层过滤

Filter 是 Servlet 规范的一部分(不属于 Spring),由 Servlet 容器(Tomcat)管理,是请求进入应用的第一道关卡

public class EncodingFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
        // 请求前:设置编码、跨域头、记录进入时间
        req.setCharacterEncoding("UTF-8");
        chain.doFilter(req, resp);   // ★ 放行到下一个 Filter / Servlet
        // 请求后:统一响应处理
    }
}

特点:① 拦截范围最广——所有进入容器的请求都过 Filter,包括静态资源、JSP、其他 Servlet(不止 SpringMVC);② 层次最外——早于 DispatcherServlet,拿不到 SpringMVC 的 Handler、Controller 方法信息;③ 靠 FilterChain 串联——多个 Filter 组成链,chain.doFilter() 放行到下一个。适用场景:编码设置、跨域(CORS)、XSS 过滤、请求日志、鉴权前置——这些「不需要知道具体调哪个 Controller」的通用请求级处理。

三、Interceptor:Spring MVC 的 Handler 级拦截

Interceptor(拦截器)是 Spring MVC 提供的,由 Spring 容器管理,在 DispatcherServlet 之后、Controller 之前拦截,能拿到「即将执行的目标 Handler」:

public class AuthInterceptor implements HandlerInterceptor {
    // Controller 执行前:能拿到 handler(目标 Controller 方法)
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) {
        // 鉴权:检查登录、权限;返回 false 则中断,不执行 Controller
        return checkLogin(req);
    }
    // Controller 执行后、视图渲染前:能拿到 ModelAndView
    public void postHandle(...) { }
    // 视图渲染后(无论成功失败):清理资源、记录耗时
    public void afterCompletion(...) { }
}

三个方法的时机是关键:preHandle(Controller 前,返回 false 中断)→ Controller 执行 → postHandle(Controller 后、渲染前)→ 视图渲染 → afterCompletion(渲染后,一定执行,用于清理)。相比 Filter,Interceptor 的优势是能拿到 Handler 信息(知道要调哪个 Controller 方法)、由 Spring 管理(方便用容器的 Bean),所以「和业务/Handler 相关」的拦截(登录校验、权限、接口耗时统计)适合用 Interceptor。

四、AOP:任意方法的最细粒度增强

AOP 是三者里最内层、粒度最细的——它不局限于 Web 请求,而是作用于任意 Spring Bean 的方法(Service、Dao、任何 Bean):

@Aspect
@Component
public class LogAspect {
    @Around("execution(* com.xx.service.*.*(..))")   // 切任意 Service 方法
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        // 方法前:能拿到方法名、参数
        Object result = pjp.proceed();   // 执行目标方法
        // 方法后:能拿到返回值
        return result;
    }
}

AOP 的独特之处:① 不限于 Controller——可以增强任意层的任意方法(这是 Filter/Interceptor 做不到的,它们只在 Web 层);② 能拿到方法级细节——方法名、参数、返回值、异常都能拿到;③ 基于动态代理——通过给 Bean 生成代理实现。适用场景:事务、日志、性能监控、权限、缓存——这些「横切多个方法」的关注点。因为粒度最细、位置最内,AOP 是三者中离业务逻辑最近的。

五、执行顺序:洋葱模型

三者的执行顺序是本题核心,遵循「由外到内进、由内到外出」的洋葱模型:

        ┌─────────── Filter ───────────┐
        │  ┌──────── Interceptor ─────┐ │
        │  │   ┌────── AOP ──────┐    │ │
        │  │   │  ┌ Controller ┐ │    │ │
   进 → │→ │→  │→ │  方法执行   │ │→   │→│ → 出
        │  │   │  └────────────┘ │    │ │
        │  │   └─────────────────┘    │ │
        │  └──────────────────────────┘ │
        └───────────────────────────────┘

具体顺序:
  Filter 前 → Interceptor.preHandle → AOP 前置 → Controller 方法
  → AOP 后置 → Interceptor.postHandle → Interceptor.afterCompletion → Filter 后

记忆要点:Filter 最外层(最先进、最后出),AOP 最内层(最后进、最先出,紧贴 Controller/方法)。这个顺序由「三者所在的层次」决定——Filter 在 Servlet 容器层(最外),Interceptor 在 SpringMVC 层(中间),AOP 在方法调用层(最内)。所以请求进来时由外向内穿过三层,响应返回时由内向外穿回。理解层次,顺序自然就记住了。

六、如何选型:按「拿什么、拦什么」

三者能力重叠又各有专长,选型看你需要什么:

需求选择原因
编码、跨域、XSS、请求日志(请求级)Filter最外层,拦所有请求,不需要 Handler 信息
登录校验、权限、接口耗时(和 Handler 相关)Interceptor能拿到目标 Controller,由 Spring 管理
事务、日志、缓存、监控(方法级、跨层)AOP粒度最细,能拿方法参数/返回值,不限于 Web

一个判断口诀:需要「拦所有请求含静态资源」用 Filter;需要「拿到 Controller 信息」用 Interceptor;需要「增强任意方法、拿参数返回值」用 AOP。三者常配合使用:Filter 做最外层的编码/跨域,Interceptor 做登录鉴权,AOP 做事务和业务日志——各司其职,覆盖从「请求级」到「方法级」的全链路。

记忆钩子:「三层由外到内:Filter(Servlet 规范,拦所有请求,最外)→Interceptor(SpringMVC,拿 Handler,中间)→AOP(任意 Bean 方法,拿参数返回值,最内);执行洋葱模型:Filter前→preHandle→AOP前→Controller→AOP后→postHandle→afterCompletion→Filter后」

七、常见误区与追问

  • 误区:Filter 和 Interceptor 一样。 Filter 是 Servlet 规范、由 Tomcat 管理、拦所有请求(含静态资源)、拿不到 Handler;Interceptor 是 SpringMVC、由 Spring 管理、只拦 DispatcherServlet 的请求、能拿到目标 Controller。
  • 误区:AOP 只能用在 Controller 上。 AOP 作用于任意 Spring Bean 的方法(Service、Dao 等),不限于 Web 层,这是它和 Filter/Interceptor 最大的不同。
  • 误区:执行顺序是 Filter→AOP→Interceptor。 是 Filter→Interceptor→AOP→Controller(由外到内),返回时反向;AOP 最内层紧贴方法。
  • 误区:Interceptor 的 afterCompletion 只在成功时执行。 无论 Controller 成功还是抛异常,afterCompletion 都会执行(类似 finally),适合做资源清理、耗时统计。
  • 追问:为什么 Filter 拿不到 Handler 而 Interceptor 能? Filter 在 Servlet 容器层、早于 DispatcherServlet,此时还没做 Handler 映射;Interceptor 在 DispatcherServlet 完成 Handler 映射之后执行,所以能拿到目标 Handler。
  • 追问:Interceptor 的 preHandle 返回 false 会怎样? 中断请求,不再执行后续拦截器、不执行 Controller;已执行过 preHandle 的拦截器的 afterCompletion 仍会被调用(用于清理)。
  • 追问:三者都能做鉴权,用哪个? 请求级的粗粒度鉴权(如 token 是否存在)用 Filter;和具体接口/权限相关的用 Interceptor(能拿到 Handler 判断需要什么权限);方法级的细粒度权限用 AOP(如 @PreAuthorize)。

八、加强记忆

Filter、Interceptor、AOP 都能「在处理前后插入逻辑」,但处在由外到内的三个层次,范围逐层缩小、粒度逐层变细:Filter 是 Servlet 规范、由 Tomcat 管理,最外层,拦所有请求(含静态资源),拿不到 Handler,适合编码/跨域/请求日志等请求级处理;Interceptor 是 Spring MVC 的、由 Spring 管理,在 DispatcherServlet 之后拦截,只拦 SpringMVC 请求、能拿到目标 Controller,适合登录鉴权/权限/接口耗时;AOP 最内层、粒度最细,作用于任意 Bean 的方法(不限 Web)、能拿到方法参数/返回值,基于动态代理,适合事务/日志/缓存。执行顺序是洋葱模型(由外到内进、由内到外出):Filter前 → Interceptor.preHandle → AOP前 → Controller方法 → AOP后 → Interceptor.postHandle → afterCompletion → Filter后。Interceptor 三方法:preHandle(前,返 false 中断)、postHandle(后、渲染前)、afterCompletion(渲染后必执行,清理用)。选型口诀「拦所有请求用 Filter、要 Handler 用 Interceptor、增强任意方法用 AOP」。一句话「Filter 最外拦一切、Interceptor 居中拿 Handler、AOP 最内切方法,洋葱模型进出」。