• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
龙师傅文徒弟
博客园    首页    新随笔    联系   管理    订阅  订阅

SpringAop使用

此文章直接进入aop的使用,aop的相关概念请自行补:

推荐链接: https://blog.csdn.net/q982151756/article/details/80513340

 

进入正题。

Advice 的5种类型:

 

  1. before advice, 在 join point 前被执行的 advice. 虽然 before advice 是在 join point 前被执行, 但是它并不能够阻止 join point 的执行, 除非发生了异常(即我们在 before advice 代码中, 不能人为地决定是否继续执行 join point 中的代码)。
  2. after return advice, 在一个 join point 正常返回后执行的 advice。
  3. after throwing advice, 当一个 join point 抛出异常后执行的 advice。
  4. after(final) advice, 无论一个 join point 是正常退出还是发生了异常, 都会被执行的 advice.。
  5. around advice, 在 join point 前和 joint point 退出后都执行的 advice. 这个是最常用的 advice.

 

实例代码:

一:前置通知: @Before

1、先建一个切面类,声明切入点,写前置通知逻辑。

@Aspect
@Component
public class AspectTest {
    //切入点
    @Pointcut("execution(* com.tan.controller..*(..))")
    public void testAspect() {

    }
    @Before(value = "testAspect()")
    public void before() {
        System.out.println("前置通知");
    }
}

测试代码,后续都是调这个接口测试:

    @GetMapping("/aop")
    public String aopTest(String id,String name) {
        //System.out.println("请求参数:"+id+",name:"+name);
        System.out.println("this is method");
        //int a = 10 / 0;
        return "这是方法执行的返回结果";
    }

运行结果:

 

 

 二:后置通知:@AfterReturning

   @AfterReturning(value = "testAspect()")
    public void afterReturning() {
        System.out.println("方法执行后而且没有异常后的通知");
    }

 

 

 三:异常通知 : @AfterThrowing

  @AfterThrowing(value = "testAspect()")
    public void afterThrowing() {
        System.out.println("异常后通知");
    }
@GetMapping("/aop")
public String aopTest(String id,String name) {
//System.out.println("请求参数:"+id+",name:"+name);
System.out.println("this is method");
int a = 10 / 0;
return "aop";
}
 

 

 

 四:最终通知 :@After

@After(value = "testAspect()")
public void after(JoinPoint joinPoint) {
System.out.println("后置通知");
}

 

 

 五:环绕通知:@Around

    @Around(value = "testAspect()")
    public Object test(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕通知: 方法前,test先执行了");
        //环绕通知=前置+目标方法执行+后置通知,proceed方法就是用于启动目标方法执行的.
        //确实是order越小越是最先执行,但更重要的是最先执行的最后结束
        //Thread.sleep(5000);
        Object s = proceedingJoinPoint.proceed();
        // System.out.println("方法名:" + proceedingJoinPoint.getSignature());
        // System.out.println("方法参数+"+ Arrays.toString(proceedingJoinPoint.getArgs()));
        //System.out.println("s是: " + s);
        System.out.println("环绕通知: 方法后");
        return "";
    }

 

 

 

ProceedingJoinPoint 类的一些常用方法:
//启动目标方法执行 :proceedingJoinPoint.proceed()
Object s = proceedingJoinPoint.proceed();
//获取方法名:proceedingJoinPoint.getSignature()
System.out.println("方法名:" + proceedingJoinPoint.getSignature());
//获取方法参数:proceedingJoinPoint.getArgs()
System.out.println("方法参数:" + Arrays.toString(proceedingJoinPoint.getArgs()));

 

 

spring 多个切面的执行顺序及原理:

https://blog.csdn.net/qq_32317661/article/details/112310508

直接总结:

这里用注解的方式:在类上加上  @Order(1)

order越小越是最先执行,但更重要的是最先执行的最后结束。

这个不难理解,Spring AOP就是面向切面编程,什么是切面,画一个图来理解下:

 

 

 

由此得出:spring aop就是一个同心圆,要执行的方法为圆心,最外层的order最小。从最外层按照AOP1、AOP2的顺序依次执行doAround方法,doBefore方法。然后执行method方法,最后按照AOP2、AOP1的顺序依次执行doAfter、doAfterReturn方法。也就是说对多个AOP来说,先before的,一定后after。

如果我们要在同一个方法事务提交后执行自己的AOP,那么把事务的AOP order设置为2,自己的AOP order设置为1,然后在doAfterReturn里边处理自己的业务逻辑。

总结:

如果两个切面中覆写的getOrder方法中返回的是0,就是还没有显式的指定不同的顺序,所以,根据跟踪源码,可以发现在order相同的情况下, 是根据切面类的名称字母序进行优先级控制的,字母序越靠前,优先级越高。字母序的比较,首先将类名转换为字符串,然后调用String的compareTo()方法,对两个类名进行比对,决定切面的排序的。如果切面类使用了@Order注解或者是实现了Ordered接口,那么可以在比对的时候自动调用getOrder()的方法,然后比较返回的值大小,值越小,优先级越高。

同一个切面类中的方法,如果有多个不同的切入方式,例如@Around,@Before,@After,@AfterReturning,@AfterThrowing,那么会先扫描出各个方法上的注解,对不同的方法按照上边注解的顺序进行排序,然后按照字母序进行排序,所以最终呈现出来的,同一个切面类中的不同切面方法的执行顺序,就会呈现如上所示的状态。

 

posted @ 2022-08-24 10:48  龙师傅文徒弟  阅读(91)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3