javaadvanced
Spring Boot AOP — Aspects and Advice
Use Spring AOP for cross-cutting concerns: logging, timing, auditing, and transaction-like behavior.
javaPress ⌘/Ctrl + Shift + C to copy
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.annotation.*;
import java.util.Arrays;
// Custom annotation to mark methods for timing
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Timed {
String value() default "";
}
// Logging aspect
@Aspect
@Component
class LoggingAspect {
private static final Logger log = LoggerFactory.getLogger(LoggingAspect.class);
// Before any controller method
@Before("execution(* com.example.controller.*.*(..))")
public void logBefore(org.aspectj.lang.JoinPoint jp) {
log.info("→ {}.{}({})",
jp.getTarget().getClass().getSimpleName(),
jp.getSignature().getName(),
Arrays.toString(jp.getArgs()));
}
// After returning
@AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
public void logAfter(org.aspectj.lang.JoinPoint jp, Object result) {
log.info("← {}.{} returned: {}",
jp.getTarget().getClass().getSimpleName(),
jp.getSignature().getName(),
result);
}
// After throwing
@AfterThrowing(pointcut = "execution(* com.example..*.*(..))", throwing = "ex")
public void logException(org.aspectj.lang.JoinPoint jp, Exception ex) {
log.error("✗ {}.{} threw: {}",
jp.getTarget().getClass().getSimpleName(),
jp.getSignature().getName(),
ex.getMessage());
}
}
// Timing aspect
@Aspect
@Component
class TimingAspect {
private static final Logger log = LoggerFactory.getLogger(TimingAspect.class);
@Around("@annotation(timed)")
public Object measureTime(ProceedingJoinPoint pjp, Timed timed) throws Throwable {
String label = timed.value().isEmpty()
? pjp.getSignature().getName() : timed.value();
long start = System.nanoTime();
try {
return pjp.proceed();
} finally {
long ms = (System.nanoTime() - start) / 1_000_000;
log.info("[TIMER] {} took {}ms", label, ms);
}
}
}
// Usage in service
@Component
class OrderService {
@Timed("process-order")
public String processOrder(String orderId) {
// Business logic
return "Processed: " + orderId;
}
}Use Cases
- Automatic method logging across services
- Performance monitoring with timing aspects
- Audit trail for sensitive operations
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
javaintermediate
Spring Boot REST Controller with CRUD
Create a complete REST API with Spring Boot: GET, POST, PUT, DELETE with validation and error handling.
Best for: Building RESTful APIs with Spring Boot
#spring-boot#rest-api
javaintermediate
Spring Boot Global Exception Handler
Centralized error handling with @ControllerAdvice for validation errors, 404s, and custom exceptions.
Best for: Consistent error responses across all endpoints
#spring-boot#error-handling
javaadvanced
Spring Security — JWT Authentication
Implement JWT authentication with Spring Security: token generation, validation, and filter chain.
Best for: Securing REST APIs with JWT tokens
#spring-boot#jwt
javaintermediate
Spring Boot — Custom Validator Annotation
Create custom validation annotations with ConstraintValidator for domain-specific field validation.
Best for: Domain-specific input validation
#spring-boot#validation