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: [email protected]
 * @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: [email protected]
 * @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裏邊處理自己的業務邏輯。

 

如果您喜歡這篇文章請在下面點個贊和收藏。謝謝您的支持!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章