Spring AOP 执行顺序详细分析

 两个不同优先级aop是拦截登录方法,执行顺序。

package com.leusysm.mgr.interceptor;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @author zhouhaiming  Email: dg_chow@163.com
 * @date 2018/11/21 10:51
 */
@Component
@Aspect
@Order(-3)
public class MessageQueueAopAspect1 {
    private static final Logger LOG = LoggerFactory.getLogger(MessageQueueAopAspect1.class);


    @Pointcut("execution(public * com.leusysm.mgr.controller.CasController.login(..))")
    private void pointCutMethod() {
    }

    //声明前置通知
    @Before("pointCutMethod()")
    public void doBefore(JoinPoint point) {
        LOG.info("MessageQueueAopAspect1:doBefore");
        return;
    }

    //声明后置通知
    @AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")
    public void doAfterReturning(JoinPoint point,Object returnValue) {
        LOG.info("MessageQueueAopAspect1:doAfterReturning");
    }

    //声明例外通知
    @AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
    public void doAfterThrowing(Exception e) {
        LOG.info("MessageQueueAopAspect1:doAfterThrowing");
    }

    //声明最终通知
    @After("pointCutMethod()")
    public void doAfter() {
        LOG.info("MessageQueueAopAspect1:doAfter");
    }

    //声明环绕通知
    @Around("pointCutMethod()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        LOG.info("MessageQueueAopAspect1:doAround-1");
        Object obj = pjp.proceed();
        LOG.info("MessageQueueAopAspect1:doAround-2");
        return obj;
    }

}

package com.leusysm.mgr.interceptor;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @author zhouhaiming  Email: dg_chow@163.com
 * @date 2018/11/21 10:53
 */
@Component
@Aspect
@Order(-4)
public class MessageQueueAopAspect2{

    private static final Logger LOG = LoggerFactory.getLogger(MessageQueueAopAspect2.class);

    @Pointcut("execution(public * com.leusysm.mgr.controller.CasController.login(..))")
    private void pointCutMethod() {
    }


    //声明前置通知
    @Before("pointCutMethod()")
    public void doBefore(JoinPoint point) {
        LOG.info("MessageQueueAopAspect2:doBefore");
        return;
    }

    //声明后置通知
    @AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")
    public void doAfterReturning(JoinPoint point,Object returnValue) {
        LOG.info("MessageQueueAopAspect2:doAfterReturning");
    }

    //声明例外通知
    @AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
    public void doAfterThrowing(Exception e) {
        LOG.info("MessageQueueAopAspect2:doAfterThrowing");
    }

    //声明最终通知
    @After("pointCutMethod()")
    public void doAfter() {
        LOG.info("MessageQueueAopAspect2:doAfter");
    }

    //声明环绕通知
    @Around("pointCutMethod()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        LOG.info("MessageQueueAopAspect2:doAround-1");
        Object obj = pjp.proceed();
        LOG.info("MessageQueueAopAspect2:doAround-2");
        return obj;
    }

}

 根据order的不同执行顺序不一样。下面是两个aop的执行顺序,order越小优先级越高。

2018-12-04 10:03:39.864 [qtp1523196930-47] INFO  c.g.l.m.i.MessageQueueAopAspect2 -MessageQueueAopAspect2:doAround-1
2018-12-04 10:03:39.865 [qtp1523196930-47] INFO  c.g.l.m.i.MessageQueueAopAspect2 -MessageQueueAopAspect2:doBefore
2018-12-04 10:03:39.865 [qtp1523196930-47] INFO  c.g.l.m.i.MessageQueueAopAspect1 -MessageQueueAopAspect1:doAround-1
2018-12-04 10:03:39.865 [qtp1523196930-47] INFO  c.g.l.m.i.MessageQueueAopAspect1 -MessageQueueAopAspect1:doBefore
2018-12-04 10:03:40.232 [qtp1523196930-47] INFO  c.g.l.m.i.MessageQueueAopAspect1 -MessageQueueAopAspect1:doAround-2
2018-12-04 10:03:40.232 [qtp1523196930-47] INFO  c.g.l.m.i.MessageQueueAopAspect1 -MessageQueueAopAspect1:doAfter
2018-12-04 10:03:40.232 [qtp1523196930-47] INFO  c.g.l.m.i.MessageQueueAopAspect1 -MessageQueueAopAspect1:doAfterReturning
2018-12-04 10:03:40.232 [qtp1523196930-47] INFO  c.g.l.m.i.MessageQueueAopAspect2 -MessageQueueAopAspect2:doAround-2
2018-12-04 10:03:40.232 [qtp1523196930-47] INFO  c.g.l.m.i.MessageQueueAopAspect2 -MessageQueueAopAspect2:doAfter
2018-12-04 10:03:40.232 [qtp1523196930-47] INFO  c.g.l.m.i.MessageQueueAopAspect2 -MessageQueueAopAspect2:doAfterReturning

从上面的测试我们看到,Order越小越是最先执行,但更重要的是最先执行的最后结束。

单个AOP执行顺序:Around-start-->Before-->Around-end-->After-->AfterReturn

多个AOP拦截同一个点,会根据order的优先级执行:

Around-start-->Before-->(嵌入优先级低的AOP执行流程)-->Around-end-->After-->AfterReturn

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

         由此得出:spring aop就是一个同心圆,要执行的方法为圆心,最外层的order最小。

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

 

如果您喜欢这篇文章请在下面点个赞和收藏。谢谢您的支持!

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值