JavaDog程序狗
JavaDog程序狗
发布于 2025-05-16 / 9 阅读
0
0

【Spring】AOP通知加载顺序比前任更难搞?来看异常时执行逻辑全解析

前言

🍊缘由

Spring AOP通知执行流程大揭秘

想象一下,AOP的通知加载顺序就像是一场热闹的派对入场顺序,每个通知都想在合适的时机闪亮登场。

异常就像是派对上突然闯入的不速之客,它一来,环绕通知和后置通知还能不能继续好好“表演”,这可真是让人摸不着头脑!就好比你精心安排了一场约会,突然天降大雨,后续的节目还能不能按计划进行呢?

今天咱就来好好唠唠这个事儿,保证让你对AOP的通知加载顺序和异常处理有全新的认识!

🐣闪亮主角

一文搞清楚AOP通知加载顺序

正常加载顺序:

异常加载顺序:

大家好,我是JavaDog程序狗

今天我要像个经验丰富的派对策划师一样,带你搞清楚AOP通知加载顺序的那些事儿,就算异常这个“捣蛋鬼”来了,咱也能知道环绕通知和后置通知到底还能不能“嗨”下去!

正文

🎯主要目标

1. AOP是什么

2. AOP有哪些通知类型

3. AOP全部通知的加载顺序是怎样的

4. 异常发生后环绕通知和后置通知还会执行吗

5. 代码示例展示AOP通知加载顺序及异常处理

🍪目标讲解

一. AOP是什么?

1. 白话理解

AOP(面向切面编程)就像是一场神奇的魔术表演。在这场表演中,核心业务逻辑就是魔术师的主要表演节目,而AOP的通知就像是在表演过程中穿插的各种特效和小惊喜。

这些特效和小惊喜可以在不影响主要表演的前提下,让整个表演更加精彩。比如说,在表演开始前可以有一段炫酷的灯光秀(前置通知),表演结束后可以有五彩斑斓的烟花(后置通知),表演过程中还可以有神秘的烟雾效果(环绕通知)等等。

2. 官方解释

官网解释:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop

在Spring框架中,AOP是通过代理模式来实现的。它允许我们在不修改原有业务逻辑的基础上,对程序进行增强,比如日志记录、事务管理等。


二. AOP有哪些通知类型?

1. 前置通知(Before Advice)

前置通知就像是派对开始前的暖场表演,在目标方法执行之前执行。它可以用来做一些准备工作,比如检查参数的合法性。

@Before("execution(* com.example.service.*.*(..))")
public void beforeAdvice() {
    System.out.println("前置通知:派对暖场开始!");
}

2. 后置通知(After Advice)

后置通知就像是派对结束后的谢幕表演,无论目标方法是否正常执行,它都会在目标方法执行之后执行。

@After("execution(* com.example.service.*.*(..))")
public void afterAdvice() {
    System.out.println("后置通知:派对谢幕啦!");
}

3. 返回通知(After Returning Advice)

返回通知就像是派对上表演成功后的欢呼,只有在目标方法正常返回结果时才会执行。

@AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
public void afterReturningAdvice(Object result) {
    System.out.println("返回通知:表演成功,欢呼!结果是:" + result);
}

4. 异常通知(After Throwing Advice)

异常通知就像是派对上突然出现的意外状况,只有在目标方法抛出异常时才会执行。

@AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "ex")
public void afterThrowingAdvice(Exception ex) {
    System.out.println("异常通知:派对出意外啦!异常信息:" + ex.getMessage());
}

5. 环绕通知(Around Advice)

环绕通知就像是派对的全程主持人,它可以在目标方法执行前后都进行操作,甚至可以决定目标方法是否执行。

@Around("execution(* com.example.service.*.*(..))")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("环绕通知:派对主持人登场,准备开场!");
    Object result = joinPoint.proceed();
    System.out.println("环绕通知:派对接近尾声,主持人总结!");
    return result;
}

三. AOP全部通知的加载顺序是怎样的?

正常情况下,AOP通知的加载顺序就像是一场精心编排的派对流程:

  1. 环绕通知(开始部分):主持人先登场,宣布派对开始。
  2. 前置通知:暖场表演开始。
  3. 目标方法:正式表演开始。
  4. 环绕通知(结束部分):主持人总结,派对接近尾声。
  5. 返回通知(如果目标方法正常返回):表演成功,欢呼。
  6. 后置通知:谢幕表演。

如果目标方法抛出异常,顺序就会变成:

  1. 环绕通知(开始部分):主持人先登场,宣布派对开始。
  2. 前置通知:暖场表演开始。
  3. 目标方法:表演过程中出意外。
  4. 异常通知:处理意外状况。
  5. 后置通知:虽然出了意外,但还是要谢幕。

四. 异常发生后环绕通知和后置通知还会执行吗?

异常发生后环绕通知

如果异常是在环绕通知调用 joinPoint.proceed() 之前抛出的,那么环绕通知的结束部分就不会执行,就好比主持人刚登场就被绊倒了,后面的总结环节自然就没了。但如果异常是在 joinPoint.proceed() 之后抛出的,环绕通知的结束部分还是会执行,因为主持人已经完成了前面的流程,总结环节还是要进行的。

异常发生后后置通知

后置通知无论目标方法是否抛出异常,都会执行。就像派对不管有没有意外状况,谢幕表演总是要有的。


五. 代码示例展示AOP通知加载顺序及异常处理

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class AopAdviceExample {

    @Before("execution(* com.example.service.*.*(..))")
    public void beforeAdvice(JoinPoint joinPoint) {
        System.out.println("前置通知:方法 " + joinPoint.getSignature().getName() + " 即将执行");
    }

    @After("execution(* com.example.service.*.*(..))")
    public void afterAdvice(JoinPoint joinPoint) {
        System.out.println("后置通知:方法 " + joinPoint.getSignature().getName() + " 执行完毕");
    }

    @AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
    public void afterReturningAdvice(JoinPoint joinPoint, Object result) {
        System.out.println("返回通知:方法 " + joinPoint.getSignature().getName() + " 返回结果:" + result);
    }

    @AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "ex")
    public void afterThrowingAdvice(JoinPoint joinPoint, Exception ex) {
        System.out.println("异常通知:方法 " + joinPoint.getSignature().getName() + " 抛出异常:" + ex.getMessage());
    }

    @Around("execution(* com.example.service.*.*(..))")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知:方法 " + joinPoint.getSignature().getName() + " 开始执行");
        Object result = null;
        try {
            result = joinPoint.proceed();
        } catch (Exception e) {
            System.out.println("环绕通知:方法 " + joinPoint.getSignature().getName() + " 执行过程中捕获到异常:" + e.getMessage());
            throw e;
        }
        System.out.println("环绕通知:方法 " + joinPoint.getSignature().getName() + " 执行结束");
        return result;
    }
}

🍈猜你想问

如何与博主联系进行探讨

关注公众号【JavaDog程序狗】

公众号回复【入群】或者【加入】,便可成为【程序员学习交流摸鱼群】的一员,问题随便问,牛逼随便吹,目前群内已有超过380+个小伙伴啦!!!

2. 踩踩博主博客

javadog.net

里面有博主的私密联系方式呦 !,大家可以在里面留言,随意发挥,有问必答😘

🍯猜你喜欢

文章推荐

【实操】Spring Cloud Alibaba AI,阿里AI这不得玩一下(含前后端源码)

【规范】看看人家Git提交描述,那叫一个规矩

【项目实战】SpringBoot+uniapp+uview2打造H5+小程序+APP入门学习的聊天小项目

【项目实战】SpringBoot+uniapp+uview2打造一个企业黑红名单吐槽小程序

【模块分层】还不会SpringBoot项目模块分层?来这手把手教你!


评论