Master SpringBoot AOP, Interceptors, and Argument Resolvers with Ready-to-Use Templates
This guide explains how to quickly set up SpringBoot AOP, interceptor, and HandlerMethodArgumentResolver development by providing Maven dependencies, annotation definitions, code templates, usage examples, and the execution order of these components.
In SpringBoot development, AOP based on dynamic proxies allows you to use annotations to capture method parameters before and after execution, enabling common tasks such as logging, status alerts, and template code injection.
Interceptors (HandlerInterceptor) and parameter resolvers (HandlerMethodArgumentResolver) serve similar purposes, allowing you to obtain method arguments for tasks like parameter assignment, validation, and path interception.
SpringBoot AOP Development Template
1. Import Maven Dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>2. Define Annotation
package com.example.demo.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime {
// optional parameters, e.g., log request args, return value, etc.
}3. Create AOP Aspect
package com.example.demo.aspect;
import com.example.demo.annotation.LogExecutionTime;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
@Component
@Aspect
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class LoggingAspect {
@Around("@annotation(com.example.demo.annotation.LogExecutionTime)")
public Object logMethodExecution(JoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object[] args = joinPoint.getArgs();
System.out.println("Method arguments: ");
for (Object arg : args) {
System.out.println(arg);
}
Object result = joinPoint.proceed();
System.out.println("Method result: " + result);
long elapsedTime = System.currentTimeMillis() - startTime;
System.out.println("Method execution time: " + elapsedTime + " ms");
return result;
}
}SpringBoot Interceptor Development Template
1. Implement Interceptor
package com.example.demo.interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class CustomInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Request URI: " + request.getRequestURI());
// assign attributes, validation, etc.
return true; // continue processing
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
org.springframework.web.context.request.WebRequest webRequest) throws Exception {
// modify response data if needed
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
if (ex != null) {
System.err.println("Exception occurred: " + ex.getMessage());
}
// final logging
}
}Common Interceptor Use Cases
Log request start and end times in preHandle and postHandle.
Permission validation based on URL or user roles.
Request parameter validation with error responses.
CORS handling in afterCompletion.
SpringBoot Parameter Resolver Development Template
HandlerMethodArgumentResolver is a Spring MVC mechanism for custom method‑parameter parsing. By defining a custom annotation (e.g., @CurrentUser) you can inject the current logged‑in user object into controller methods.
1. Define Custom Annotation
package com.example.demo.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUser {
// optional attributes, e.g., required = true
}2. Implement HandlerMethodArgumentResolver
package com.example.demo.resolver;
import com.example.demo.annotation.CurrentUser;
import com.example.demo.model.User;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.servlet.http.HttpServletRequest;
@Component
public class CurrentUserMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterAnnotation(CurrentUser.class) != null;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
org.springframework.web.context.request.NativeWebRequest webRequest,
org.springframework.web.bind.support.WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
// Retrieve user from session or security context
return (User) request.getSession().getAttribute("currentUser");
}
}3. Register Resolver and Interceptor
package com.example.demo.config;
import com.example.demo.interceptor.CustomInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import java.util.List;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public CustomInterceptor customInterceptor() {
return new CustomInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(customInterceptor()).addPathPatterns("/**");
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new CurrentUserMethodArgumentResolver());
}
}4. Use Annotation in Controller
package com.example.demo.controller;
import com.example.demo.annotation.CurrentUser;
import com.example.demo.model.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/profile")
public String getUserProfile(@CurrentUser User user) {
return "Current user: " + user.getUsername();
}
}Execution Order
Request reaches DispatcherServlet.
Interceptor preHandle methods execute (in order).
HandlerMethodArgumentResolver parses method parameters.
AOP @Before advice runs.
Controller method executes.
AOP @Around advice (if present) wraps execution.
AOP @After advice runs.
Interceptor postHandle methods execute.
View rendering.
Interceptor afterCompletion methods execute.
Lin is Dream
Sharing Java developer knowledge, practical articles, and continuous insights into computer engineering.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
