Details of spring AOP execution sequence instances

Time:2020-3-24

This article mainly introduces the detailed explanation of spring AOP execution sequence examples. In this article, the example code is introduced in great detail, which has a certain reference learning value for your study or work. You can refer to the following for your friends

As we all know, spring declarative transactions are implemented based on AOP, so if we customize multiple AOPs in the same method, how can we specify their execution order?

Many of the answers on the Internet are to specify an order. The smaller the order is, the earlier it will be executed. This is not a mistake, but it is one-sided.

There are three ways to configure AOP execution order:

By implementing the org.springframework.core.ordered interface


@Component 
@Aspect 
@Slf4j 
public class MessageQueueAopAspect1 implements Ordered{@Override 
  public int getOrder() { 
    // TODO Auto-generated method stub 
    return 2; 
  } 
   
} 

By annotation


@Component 
@Aspect 
@Slf4j 
@Order(1) 
public class MessageQueueAopAspect1{ 
   
  ... 
} 

Configure through profile


<aop:config expose-proxy="true"> 
  <aop:aspect ref="aopBean" order="0">  
    <aop:pointcut expression="@annotation(xxx.xxx.xxx.annotation.xxx)"/>  
    <aop:around pointcut-ref="testPointcut" method="doAround" />  
    </aop:aspect>  
</aop:config> 

Let’s add the following two AOPs to the same method to see what happens.

@Component 
@Aspect 
@Slf4j 
public class MessageQueueAopAspect1 implements Ordered{ 
   
  @Resource(name="actionMessageProducer") 
  private IProducer<MessageQueueInfo> actionProducer;   
   
  @Pointcut("@annotation(com.xxx.annotation.MessageQueueRequire1)") 
  private void pointCutMethod() { 
  } 
   
  //Pre notice of declaration 
  @Before("pointCutMethod()") 
  public void doBefore(JoinPoint point) { 
    log.info("MessageQueueAopAspect1:doBefore"); 
    return; 
  } 
 
  //Post declaration notice 
  @AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue") 
  public void doAfterReturning(JoinPoint point,Object returnValue) { 
    log.info("MessageQueueAopAspect1:doAfterReturning"); 
  } 
 
  //Declaration exception notice 
  @AfterThrowing(pointcut = "pointCutMethod()", throwing = "e") 
  public void doAfterThrowing(Exception e) { 
    log.info("MessageQueueAopAspect1:doAfterThrowing"); 
  } 
 
  //Statement final notice 
  @After("pointCutMethod()") 
  public void doAfter() { 
    log.info("MessageQueueAopAspect1:doAfter"); 
  } 
 
  //Announcement surround notification 
  @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; 
  } 
   
  @Override 
  public int getOrder() { 
    return 1001; 
  } 
}
@Component 
@Aspect 
@Slf4j 
public class MessageQueueAopAspect2 implements Ordered{ 
   
  @Resource(name="actionMessageProducer") 
  private IProducer<MessageQueueInfo> actionProducer;   
   
  @Pointcut("@annotation(com.xxx.annotation.MessageQueueRequire2)") 
  private void pointCutMethod() { 
  } 
   
   
  //Pre notice of declaration 
  @Before("pointCutMethod()") 
  public void doBefore(JoinPoint point) { 
    log.info("MessageQueueAopAspect2:doBefore"); 
    return; 
  } 
 
  //Post declaration notice 
  @AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue") 
  public void doAfterReturning(JoinPoint point,Object returnValue) { 
    log.info("MessageQueueAopAspect2:doAfterReturning"); 
  } 
 
  //Declaration exception notice 
  @AfterThrowing(pointcut = "pointCutMethod()", throwing = "e") 
  public void doAfterThrowing(Exception e) { 
    log.info("MessageQueueAopAspect2:doAfterThrowing"); 
  } 
 
  //Statement final notice 
  @After("pointCutMethod()") 
  public void doAfter() { 
    log.info("MessageQueueAopAspect2:doAfter"); 
  } 
 
  //Announcement surround notification 
  @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; 
  } 
   
  @Override 
  public int getOrder() { 
    return 1002; 
  } 
}

@Transactional(propagation=Propagation.REQUIRES_NEW) 
@MessageQueueRequire1 
@MessageQueueRequire2 
public PnrPaymentErrCode bidLoan(String id){ 
       ... 
    } 

Look at the execution results:

From the above test, we can see that the smaller the order is, the more important it is, the last end of the first execution.

It’s not hard to understand. Spring AOP is face-to-face programming. What is face-to-face? Draw a diagram to understand:

It is concluded that spring AOP is a concentric circle, the method to be executed is the center of the circle, and the outermost order is the smallest. From the outermost layer, execute doaround method and dobefore method in the order of aop1 and Aop2. Then execute the method method, and finally execute the doafter and doafterreturn methods in the order of Aop2 and aop1. That is to say, for multiple AOPs, before and after.

If we want to execute our own AOP after the same method transaction is committed, set the AOP order of the transaction to 2, set our own AOP order to 1, and then process our own business logic in the doAfterReturn.

The above is the whole content of this article. I hope it will help you in your study, and I hope you can support developepaer more.