Careeroza
Pointcut Expressions
Common Pointcuts
| Expression | Matches |
|---|---|
execution(* com.shopease.service.*.*(..)) | any method of any class directly in the service package |
execution(* com.shopease..*Service.*(..)) | methods of classes ending in Service, any sub-package |
execution(public * *(..)) | every public method |
within(com.shopease.controller..*) | all methods inside controller classes |
@annotation(com.shopease.aop.Timed) | methods annotated with @Timed |
bean(orderService) | the bean named orderService |
Execution syntax: execution(modifiers? returnType declaringType? methodName(params) throws?). * = any one thing, .. = any number (of packages or parameters). Combine with &&, || and !.
Annotation-Driven Pointcuts
A custom annotation is the cleanest way: only methods you mark are advised.
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecution {
String value() default "";
}
@Aspect
@Component
@Slf4j
public class LogExecutionAspect {
@Around("@annotation(logExecution)")
public Object log(ProceedingJoinPoint pjp, LogExecution logExecution) throws Throwable {
String name = logExecution.value().isEmpty() ? pjp.getSignature().getName() : logExecution.value();
log.info("-> {} args={}", name, Arrays.toString(pjp.getArgs()));
Object result = pjp.proceed();
log.info("<- {} result={}", name, result);
return result;
}
}
@Service
public class CheckoutService {
@LogExecution("checkout")
public OrderResponse checkout(Long cartId) { ... }
}Practice
Exercise: Write an @AfterThrowing advice that logs every exception thrown from any class in com.shopease.service or its sub-packages.
Show answer
@Aspect
@Component
@Slf4j
public class ErrorLoggingAspect {
@AfterThrowing(pointcut = "execution(* com.shopease.service..*(..))", throwing = "ex")
public void logError(JoinPoint jp, Exception ex) {
log.error("{} failed: {}", jp.getSignature().toShortString(), ex.getMessage());
}
}