AOP 实战小记

AOP 实战

常见注解

@Aspect

  • 用于定义一个切面,将横切逻辑封装在切面中。

  • 切面是包含切入点和通知的类。

  • 示例代码:

    @Aspect
    @Component
    public class LoggingAspect {
        // 切面类的实现
    }
    

@Pointcut

  • 用于定义一个切入点,指定在哪些连接点上应用切面逻辑。

  • 可以在多个通知中重复使用同一个切入点。

  • 示例代码:

    @Pointcut("execution(* com.example.service.*.*(..))")
    private void serviceLayer() {}
    

@Before

  • 用于定义一个前置通知,在方法执行之前执行切面逻辑。

  • 在连接点之前执行。

  • 示例代码:

    @Before("serviceLayer()")
    public void beforeAdvice() {
        // 执行前置通知逻辑
    }
    

@After

  • 用于定义一个后置通知,在方法执行之后执行切面逻辑(无论方法是否抛出异常)。

  • 在连接点之后执行。

  • 示例代码:

    @After("serviceLayer()")
    public void afterAdvice() {
        // 执行后置通知逻辑
    }
    

@AfterReturning

  • 用于定义一个返回后通知,在方法正常返回后执行切面逻辑。

  • 只在方法正常返回时执行,在方法抛出异常时不执行。

  • 示例代码:

    @AfterReturning(pointcut = "serviceLayer()", returning = "result")
    public void afterReturningAdvice(Object result) {
        // 执行返回后通知逻辑
    }
    

@AfterThrowing

  • 用于定义一个异常通知,在方法抛出异常后执行切面逻辑。

  • 只在方法抛出异常时执行,在方法正常返回时不执行。

  • 示例代码:

    @AfterThrowing(pointcut = "serviceLayer()", throwing = "exception")
    public void afterThrowingAdvice(Exception exception) {
        // 执行异常通知逻辑
    }
    

@Around

  • 用于定义一个环绕通知,在方法执行前后执行切面逻辑,并控制方法的执行。

  • 在连接点之前和之后执行。

  • 示例代码:

    @Around("serviceLayer()")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        // 执行前置逻辑
        Object result = joinPoint.proceed(); // 执行被通知的方法
        // 执行后置逻辑
        return result;
    }
    

环绕通知是如何判定前后的?

在使用 AOP 的环绕通知(@Around)时,你可以通过 ProceedingJoinPoint 对象的 proceed() 方法来决定是执行前还是执行后。

  • proceed() 方法的作用是:执行被通知(advice)的目标方法。

以下是如何控制执行时机的详细说明:

执行前(Before)

在调用 proceed() 方法之前,你可以执行任何你需要在目标方法执行之前的逻辑。这通常包括验证、设置上下文信息、记录日志等。例如:

public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {
    // 执行前的逻辑,例如权限检查
    checkPermission(authCheck);

    try {
        // 继续执行目标方法
        return joinPoint.proceed();
    } catch (Throwable e) {
        // 异常处理逻辑
        handleException(e);
        throw e;
    }
}

在这个例子中,checkPermission 方法会在目标方法执行前被调用,用于进行权限检查。如果权限检查通过,joinPoint.proceed() 会被调用,从而执行目标方法。

执行后(After)

目标方法的执行可以在 proceed() 方法调用后被认为是“执行后”。一旦 proceed() 方法被调用,目标方法就会开始执行。目标方法执行完成后,你可以在 proceed() 方法之后执行任何清理或后续操作。例如:

public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {
    try {
        // 执行前的逻辑
        checkPermission(authCheck);
        // 执行目标方法
        return joinPoint.proceed();
    } catch (Throwable e) {
        // 异常处理逻辑
        handleException(e);
        throw e;
    } finally {
        // 执行后的逻辑,无论目标方法是否成功执行都会执行
        cleanupResources();
    }
}

在这个例子中,cleanupResources 方法会在 proceed() 方法调用之后执行,无论目标方法是否成功执行。这使得 finally 块成为执行清理逻辑的理想位置。

异常处理

如果在目标方法执行过程中抛出异常,你可以在 catch 块中捕获并处理这些异常。这允许你在方法执行后进行异常处理,同时仍然可以在 finally 块中执行清理逻辑。

总结一下,通过控制 proceed() 方法的调用时机,你可以在目标方法执行前后执行自定义的逻辑。使用 AOP 的环绕通知提供了一种灵活的方式来在方法执行的不同阶段插入横切关注点。

学习参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值