AOP - AspectJ

目标bean

package com.example.service;

import org.springframework.stereotype.Component;

@Component
public class UserService {
    public String sayHello() {
        return "Hello!";
    }
}

示例1

// 自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogExecution {
}

// 切面
@Aspect
@Order(100)
public class AnnotationAspect {

    // 切点表达式没有抽出来。(前置通知中如果 return,目标方法不会执行)
    @Before("@annotation(LogExecution)")
    public void logBeforeAnnotatedMethod() {
        System.out.println("Executing annotated method...");
    }
}

示例2

@Aspect
@Order(10)
public class LoggingAspect {

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

    /**
     * 前置通知,参数表示连接点,可以获取方法,参数信息,是可选的。(前置通知中如果 return,目标方法不会执行)
     */
    @Before("serviceMethods()")
    public void logBefore(JoinPoint joinPoint) {
        // 获取方法名称
        String methodName = joinPoint.getSignature().getName();
        // 获取方法参数
        Object[] methodArgs = joinPoint.getArgs();
        System.out.println("前置通知:方法 " + methodName + " 开始执行");
    }

    /**
     * 后置通知,不管方法是否发生异常都会通知
     */
    @After("serviceMethods()")
    public void logAfter(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("前置通知:方法 " + methodName + " 执行结束");
    }

    /**
     * 返回通知,发生异常不会通知,如果要获取结果要通过 returning 指定接收结果的参数名称
     */
    @AfterReturning(pointcut = "serviceMethods()", returning = "result")
    public void logAfterReturning(Object result) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("返回通知:方法 " + methodName + " 正常执行完毕,结果为:" + result);
    }

    /**
     * 异常通知,当目标方法发生异常时通知,如果要知道是什么异常,也要指定接收异常的参数名称,通过 throwing 来指定
     */
    @AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")
    public void logAfterThrowing(Throwable ex) {
        System.out.println("异常通知:方法 " + methodName + " 发生异常,异常为:" + ex);
    }
}

示例3

/**
 * 环绕通知,四合一通知
 * ProceedingJoinPoint 是 JoinPoint 子接口,扩展了执行目标方法的能力
 * 如果发生异常要跑出去,因为可能是多层代理,发生异常不抛出去的话,上层代理不知道发生了异常,就会拿到返回值是 null 做后续处理
 */
@Around("serviceMethods()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("Before..."); // 前置通知通知
    Object result = null;
    try {
        result = joinPoint.proceed(); // 执行目标方法
        System.out.println("AfterReturning"); // 没发生异常,可以做返回通知
    } catch (Exception e) {
        System.out.println("AfterThrowing..."); // 发生异常,可以做异常通知
        throw e; // 抛出异常
    } finally {
        System.out.println("After..."); // 后置通知
    }
    return result;
}
posted @   CyrusHuang  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示