AOP - AspectJ

CyrusHuang發表於2024-10-20
// 自定義註解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogExecution {
}

@Aspect // 切面類
@Order(1000) // 數字越小,優先順序越高
@Component // 也要註冊到容器
public class LoggingAspect {

    // 定義切點
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceMethods() {}

    // 前通知
    @Before("serviceMethods()")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Executing method...");
        System.out.println("Before method: " + joinPoint.getSignature());
    }

    // 後通知
    @After("serviceMethods()")
    public void logAfter(JoinPoint joinPoint) {
        System.out.println("Method execution completed.");
    }

    // 返回通知
    @AfterReturning(pointcut = "serviceMethods()", JoinPoint joinPoint, returning = "result")
    public void logAfterReturning(Object result) {
        System.out.println("Method returned: " + result);
    }

    // 異常通知
    @AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")
    public void logAfterThrowing(Throwable ex) {
        System.out.println("Method threw an exception: " + ex);
    }

    // 環繞通知(四合一通知)
    @Around("serviceMethods()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Before..."); // 前通知
        Object[] args = joinPoint.getArgs(); // 引數
        try {
            Object result = joinPoint.proceed(); // 執行目標方法
            System.out.println("AfterReturning"); // 返回通知
        } catch {
            System.out.println("AfterThrowing..."); // 異常通知
        } finally {
            System.out.println("After..."); // 後通知
        }
        return result;
    }

    // 使用自定義註解的通知
    @Before("@annotation(LogExecution)")
    public void logBeforeAnnotatedMethod() {
        System.out.println("Executing annotated method...");
    }
}

相關文章