前言
🍊缘由
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通知的加载顺序就像是一场精心编排的派对流程:
- 环绕通知(开始部分):主持人先登场,宣布派对开始。
- 前置通知:暖场表演开始。
- 目标方法:正式表演开始。
- 环绕通知(结束部分):主持人总结,派对接近尾声。
- 返回通知(如果目标方法正常返回):表演成功,欢呼。
- 后置通知:谢幕表演。
如果目标方法抛出异常,顺序就会变成:
- 环绕通知(开始部分):主持人先登场,宣布派对开始。
- 前置通知:暖场表演开始。
- 目标方法:表演过程中出意外。
- 异常通知:处理意外状况。
- 后置通知:虽然出了意外,但还是要谢幕。
四. 异常发生后环绕通知和后置通知还会执行吗?
异常发生后环绕通知
如果异常是在环绕通知调用 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. 踩踩博主博客
里面有博主的私密联系方式呦 !,大家可以在里面留言,随意发挥,有问必答😘
🍯猜你喜欢
文章推荐
【实操】Spring Cloud Alibaba AI,阿里AI这不得玩一下(含前后端源码)
【项目实战】SpringBoot+uniapp+uview2打造H5+小程序+APP入门学习的聊天小项目
【项目实战】SpringBoot+uniapp+uview2打造一个企业黑红名单吐槽小程序
【模块分层】还不会SpringBoot项目模块分层?来这手把手教你!