Interview Prep Zoneby CuriouserLabs

Question 3 of 5 · senior level

Filters vs HandlerInterceptors vs AOP — where do you put which cross-cutting web concern?

🎤 Say this first

Ordered by proximity to the metal: Filters (Servlet spec, before/after the entire servlet — can wrap/short-circuit request & response streams): security, CORS, compression, correlation-ID, rate limiting. Interceptors (Spring MVC, know the handler): auth-adjacent checks needing controller context, tenant resolution, handler timing. AOP (service layer, knows business methods): transactions, retries, domain audit. Rule of thumb: body/stream manipulation → filter; handler-aware web concern → interceptor; business-boundary concern → aspect.

The full picture

FilterInterceptorAOP aspect
LayerServlet containerSpring MVC (inside DispatcherServlet)Any bean method
Knows the matched handler?✅ (HandlerMethod, annotations)n/a — knows the method
Can wrap request/response body✅ (wrappers)❌ (response may be committed)
Sees non-MVC traffic (static, /error)mapping-dependent
Typical residentsSecurity chain, CORS, gzip, MDC/correlationtenant context, deprecation headers, per-handler metricstransactions, retries, caching, domain audit
  • Interceptor hooks: preHandle (veto-capable), postHandle (before view render; useless for @ResponseBody bodies — already written), afterCompletion (finally — cleanup, timing).
  • Order story end-to-end: container filters → security filter chain → DispatcherServlet → interceptors(pre) → argument resolvers → controller → advice(on error) → interceptors(after) → filters unwind. Being able to narrate this is the senior answer.
  • Caching request bodies for logging requires ContentCachingRequestWrapper in a filter — bodies are one-shot streams; naive logging breaks deserialization downstream.
  • Exceptions in filters bypass @ControllerAdvice (previous question's warning) — keep filter logic minimal and fail into well-defined responses.

🔄 Likely follow-up questions

  • Why can't postHandle modify a @ResponseBody response?
  • How do you order custom filters relative to Spring Security's chain?
  • Where would you implement idempotency keys and why?