Spring AOP aspect execution sequence practice

Keywords: Java Spring AOP

People who have used SpringAop know that this thing is very powerful and can realize many of our cross-sectional functions, including many of Spring's own things. For example, the implementation of transaction (@ Transactional) and cache (@ Cacheable) depend on aspects. What is the execution order of aspects after a method is modified by multiple aspect annotations? If you change the execution order of existing aspects in Spring, let's practice them one by one.

1, Execution order of custom cut plane

Define two section annotations @ AopOne @AopTwo

Write the logic of two aspects

package chen.huai.jie.springboot.aop.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @author chenhj_sh
 */
@Slf4j
@Aspect
@Component
@Order(value = 20)
public class AopOneAspect {

    /**
     * @Description Define pointcuts
     */
    @Pointcut(value = "@annotation(chen.huai.jie.springboot.aop.annotation.AopOne)")
    public void pointCut() {

    }

    /**
     * Around Advice 
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("pointCut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("Before execution of section 1");
        Object result = joinPoint.proceed();
        log.info("After execution of section 1");
        return result;
    }
}
package chen.huai.jie.springboot.aop.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @author chenhj_sh
 */
@Slf4j
@Aspect
@Component
@Order(value = 11)
public class AopTwoAspect {

    /**
     * @Description Define pointcuts
     */
    @Pointcut(value = "@annotation(chen.huai.jie.springboot.aop.annotation.AopTwo)")
    public void pointCut() {

    }

    /**
     * Around Advice 
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("pointCut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("Before execution of section 2");
        Object result = joinPoint.proceed();
        log.info("After execution of section 2");
        return result;
    }
}

Method execution:

package chen.huai.jie.springboot.aop.service;

import chen.huai.jie.springboot.aop.annotation.AopOne;
import chen.huai.jie.springboot.aop.annotation.AopTwo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @author chenhuaijie
 */
@Slf4j
@Service
public class AopService {

    @AopOne
    @AopTwo
    public void aop() {
        log.info("Execute business logic");
    }
}

Execution results:

Because the order of section 2 is 11, which is smaller than that of section 1, Section 2 is executed first. Note that the execution of section 2 is actually a concentric circle, which is executed first and then finished, as shown in the following figure:

 

 

2, Execution order of custom aspect and Spring built-in aspect

In addition to the above customized section annotations, many times our customized annotations may be used together with the annotations already made in Spring. For example, I made a distributed lock annotation @ DistributedLock, which may be used together with the @ Transactional @Cacheable annotation

When used with transaction annotations, we want the distributed lock annotation to execute before the transaction annotation and after the end of the transaction annotation.

When used with cache annotations, in order to prevent cache breakdown, we need cache annotations to take precedence over distributed lock annotations.

How? How to change the execution logic of some aspects built in Spring? As follows:

@EnableCaching(order = 10)

@EnableTransactionManagement(order  = 15)

The orderz field in these two annotations can change the execution order of their respective sections, which can meet our requirements.

Examples of custom annotations and transaction annotations:

Transactions take precedence over custom annotation execution:

Transaction execution after custom annotation:  

Summary:

Record the development process bit by bit and grow with everyone.

Posted by php_joe on Wed, 22 Sep 2021 20:36:53 -0700