面试题:能说说 Spring 拦截链的实现吗?

Spring 中的拦截链(Interceptor Chain)通常用于在请求处理的过程中插入额外的逻辑,比如日志记录、权限验证、性能监控等。拦截链的核心思想是通过 责任链模式(Chain of Responsibility Pattern) 将多个拦截器串联起来,每个拦截器都可以对请求进行处理或拦截。

在 Spring 中,拦截链的实现主要体现在以下两个场景:

  1. Spring MVC 中的拦截器(HandlerInterceptor)
  2. Spring AOP 中的拦截器(MethodInterceptor)

以下分别对这两种拦截链的实现进行详细说明。


1. Spring MVC 中的拦截链

Spring MVC 提供了 HandlerInterceptor 接口,用于在请求处理的不同阶段插入自定义逻辑。拦截器可以应用于控制器(Controller)的请求处理过程中。

(1)HandlerInterceptor 接口

HandlerInterceptor 接口定义了三个方法:

  • preHandle:在控制器方法执行之前调用。如果返回 false,则中断请求处理链。
  • postHandle:在控制器方法执行之后、视图渲染之前调用。
  • afterCompletion:在请求完成之后调用(视图渲染完成后),通常用于资源清理。
public interface HandlerInterceptor {
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
    void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;
    void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;
}

(2)拦截链的执行流程

Spring MVC 的拦截链由 DispatcherServlet 驱动,执行流程如下:

  1. preHandle
    • 按顺序调用所有拦截器的 preHandle 方法。
    • 如果某个拦截器的 preHandle 返回 false,则后续拦截器和控制器方法都不会执行。
  2. 控制器方法执行
    • 如果所有拦截器的 preHandle 都返回 true,则执行控制器方法。
  3. postHandle
    • 按逆序调用所有拦截器的 postHandle 方法。
  4. 视图渲染
    • 渲染视图(如 JSP、Thymeleaf 等)。
  5. afterCompletion
    • 按逆序调用所有拦截器的 afterCompletion 方法。

(3)配置拦截器

可以通过实现 WebMvcConfigurer 接口或继承 WebMvcConfigurerAdapter 类来配置拦截器:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoggingInterceptor());
        registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/secure/**");
    }
}

(4)示例:日志拦截器

public class LoggingInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("Before handling request: " + request.getRequestURI());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        System.out.println("After handling request: " + request.getRequestURI());
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.println("Request completed: " + request.getRequestURI());
    }
}

2. Spring AOP 中的拦截链

Spring AOP 通过 动态代理 实现拦截链,支持方法级别的拦截。核心接口是 MethodInterceptor

(1)MethodInterceptor 接口

MethodInterceptor 是 AOP 联盟(AOP Alliance)定义的接口,用于在方法调用前后插入逻辑。

public interface MethodInterceptor extends Interceptor {
    Object invoke(MethodInvocation invocation) throws Throwable;
}

(2)拦截链的执行流程

Spring AOP 的拦截链由 ProxyFactory 或 ProxyFactoryBean 驱动,执行流程如下:

  1. 创建代理对象
    • 为目标对象创建代理(JDK 动态代理或 CGLIB 代理)。
  2. 调用拦截器
    • 按顺序调用所有拦截器的 invoke 方法。
    • 每个拦截器可以决定是否继续执行链中的下一个拦截器或目标方法。
  3. 执行目标方法
    • 如果所有拦截器都允许继续执行,则调用目标方法。
  4. 返回结果
    • 将目标方法的返回值传递给拦截器链,最终返回给调用者。

(3)配置拦截器

可以通过 XML 或注解方式配置 AOP 拦截器。

示例:基于注解的 AOP 拦截器

@Aspect
@Component
public class LoggingAspect {
    @Around("execution(* com.example.service.*.*(..))")
    public Object logMethodCall(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Before method: " + joinPoint.getSignature().getName());
        Object result = joinPoint.proceed(); // 继续执行拦截链或目标方法
        System.out.println("After method: " + joinPoint.getSignature().getName());
        return result;
    }
}

示例:基于 XML 的 AOP 拦截器

<bean id="loggingInterceptor" class="com.example.LoggingInterceptor" />

<aop:config>
    <aop:pointcut id="serviceMethods" expression="execution(* com.example.service.*.*(..))" />
    <aop:advisor advice-ref="loggingInterceptor" pointcut-ref="serviceMethods" />
</aop:config>

运行 HTML


3. Spring 拦截链的核心设计

无论是 Spring MVC 还是 Spring AOP,拦截链的核心设计都是基于 责任链模式

  • 每个拦截器都是一个独立的处理器,负责处理特定的逻辑。
  • 拦截器之间通过链式调用串联起来,每个拦截器可以决定是否继续执行链中的下一个拦截器。
  • 拦截链的执行顺序可以通过配置控制。

4. Spring MVC 拦截链 vs Spring AOP 拦截链

特性Spring MVC 拦截链Spring AOP 拦截链
应用场景主要用于 Web 请求处理。主要用于方法级别的拦截。
核心接口HandlerInterceptorMethodInterceptor
执行时机请求处理的不同阶段(如 preHandle)。方法调用前后。
配置方式通过 WebMvcConfigurer 配置。通过 AOP 注解或 XML 配置。
依赖依赖于 Spring MVC 框架。依赖于 Spring AOP 框架。

总结

Spring 拦截链的实现基于责任链模式,分为 Spring MVC 拦截链和 Spring AOP 拦截链:

  • Spring MVC 拦截链:用于 Web 请求处理,支持在请求处理的不同阶段插入逻辑。
  • Spring AOP 拦截链:用于方法级别的拦截,支持在方法调用前后插入逻辑。

拦截链的设计使得 Spring 应用程序可以灵活地扩展功能,同时保持代码的模块化和可维护性。

THE END
点赞10 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容