AOP core code + usage notes

1. Noun introduction

1. Connection point (JoinPoint)

A connection point is a point that can be inserted into an aspect during application execution. These points can be when a method is called or even when a field is modified. It is a virtual concept. For example, when taking the subway, you can get off at every station, so every station is an access point. If there are multiple methods in an object, then each method is a connection point.

2. Pointcut

The entry point is the connection point of some special envoys, and is the place where specific notices are attached. For example, when you take the subway and get off at a certain station, then this station is the entry point

  1. The connection point is a virtual concept, which can be understood as all the opportunities that meet the scanning conditions of the cut point.
  2. A specific example: For example, when driving through a highway, there are many exits (connection points) on this highway, but we will not go out at every exit, but we will only choose the exit (cutting point) we need to go out. .
  3. Simply understand that each exit is a connection point, but the exit we use is the point of contact. Each application has multiple locations suitable for weaving notifications, and these locations are connection points. But only the specific location we choose is the point of contact.

3. Aspect

The aspect is the combination of the notice and the entry point. The notice stipulates when and what to do, and the entry point stipulates where. Such as "get off at West Station at 8 o'clock" is a cross section. Then at 8 o'clock, the action to get off is a notification. West Station is an entry point.

4. Introduction

Allows us to add new method attributes to existing classes.

5. Weaving

The process of applying aspects to target objects and creating proxy objects. The tangent point is woven into the target object at the specified connection point (tangent point). In the life cycle of a target, there are multiple points that can be woven into:

Compile period, class loading period, runtime

6. Advice

The notification defines when and what to do. The types of notifications are as follows:

Insert picture description here

They are: post notification, return notification, exception notification, surround notification, and front notification


2. Coordinates and template code

Add AOP dependency

   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
  </dependency>

The following is the template code

@Slf4j
@Aspect
@Component
public class SysLogAspect {
    
    
    /**
     * @Pointcut注解用于定义切入点
     * bean("spring容器中bean的名字")这个表达式为切入点表达式定义的一种语法,
     * 它描述的是某个bean或多个bean中所有方法的集合为切入点,这个形式的切入点
     * 表达式的缺陷是不能精确到具体方法的.
     */
    @Pointcut("bean(sysUserServiceImpl)")
    public void doLog(){
    
    }//此方法只负责承载切入点的定义

    /**
     * @Around注解描述的方法,可以在切入点执行之前和之后进行业务拓展,
     * 在当前业务中,此方法为日志通知方法
     * @param joinPoint 连接点对象,此对象封装了要执行的切入点方法信息.
     * 可以通过连接点对象调用目标方法,这里的ProceedingJoinPoint类型只能应用于@Around描述的方法参数中
     * @return 目标方法的执行结果
     * @throws Throwable
     */
    @Around("doLog()")
    public Object doAround(ProceedingJoinPoint jp)throws Throwable{
    
    
        log.info("Start:{}",System.currentTimeMillis());
        try {
    
    
            Object result = jp.proceed();//执行目标方法(切点方法中的某个方法)
            log.info("After:{}",System.currentTimeMillis());
            return result;//目标业务方法的执行结果
        }catch(Throwable e){
    
    
            e.printStackTrace();
            log.error("Exception:{}",System.currentTimeMillis());
            throw e;
        }
    }
}

3. Bottom analysis

Analysis of the working principle of Spring aspects

When the target business method corresponding to the entry point inside our aspect is executed, the bottom layer will access the notification method in the aspect through the proxy object, and then use the notification method to enhance the target business.

Insert picture description here

The application analysis of the JDK dynamic proxy object in the project, as shown in the figure:

Insert picture description here

Among them: the default AOP proxy of the springboot project is the CGLIB proxy. If you want to be a JDK proxy, you need to configure the following in the springboot configuration file:

spring: 
  aop: 
    proxy-target-class: false

CGLIB dynamic proxy object application analysis in the project, as shown in the figure:

Insert picture description here

4. Advanced application of AOP technology in Spring

AOP notification type

The Spring Framework AOP module defines notification types, which are as follows:

  • @Around (The notification with the highest priority among all notifications can be flexibly expanded before and after the execution of the target method.)
  • @Before (Called before the target method is executed)
  • @AfterReturning (executed when the target method ends normally)
  • @AfterThrowing (executed when the target method ends abnormally)
  • @After (execute when the target method ends, it will be executed when the target method ends normally and abnormally)

Based on the understanding of notification types, analyze the specific execution time of the notification through case analysis, and analyze the key code

package com.chen.service.aspect;
@Aspect
@Component
public class SysTimeAspect {
    
    
    @Pointcut("bean(sysRoleServiceImpl)")
    public void doTime(){
    
    }

    @Before("doTime()")
    public void doBefore(JoinPoint jp){
    
    
        System.out.println("@Before");
    }

    @After("doTime()")
    public void doAfter(){
    
    
        System.out.println("@After");
    }

    @AfterReturning("doTime()")
    public void doAfterReturning(){
    
    
        System.out.println("@AfterReturning");
    }

    @AfterThrowing("doTime()")
    public void doAfterThrowing(){
    
    
        System.out.println("@AfterThrowing");
    }
    //最重要,优先级也是最高
    @Around("doTime()")
    public Object doAround(ProceedingJoinPoint joinPoint)throws Throwable{
    
    
        try {
    
    
            System.out.println("@Around.before");
            Object result = joinPoint.proceed();
            System.out.println("@Around.AfterReturning");
            return result;
        }catch(Exception e){
    
    
            System.out.println("@Around.AfterThrowing");
            e.printStackTrace();
            throw e;
        }finally {
    
    
            System.out.println("@Around.after");
        }
    }

}

Among them, it is not necessary to define all notification methods in actual projects, and notification methods will be added in combination with specific businesses.

AOP entry point expression

In the Spring project, the pointcut expression can be divided into two types:

  • Coarse-grained entry point expression definition (not precise to the specific method), such as bean, within expression
  • Fine-grained entry point expression definition (can be precise to the specific method), such as execution, @annotation expression

Coarse-grained pointcut expression

  • bean ("bean's name") expression case analysis
1) bean(sysUserServiceImpl),sysUserServiceImpl类中所有方法集合为切入点
2) bean(*ServiceImpl),以ServiceImpl结尾的所有方法集合为切入点
  • within ("package name. type") expression case analysis
1) within(com.pj.service.SysUserServiceImpl),SysUserServiceImpl类中所有方法集合为切入点
2) within(com.pj.service.*),com.pj.service包下所有类中的方法集合为切入点
3) within(com.pj.service..*),com.pj.service包以及子包中所有类中方法的集合为切入点

Fine-grained entry point expression

  • execution ("Return value class full name. Method name (parameter list)") expression case analysis
1) execution(int com.cy.pj.service.SysUserService.validById(Integer,Integer))
2) execution(* com.cy.pj.service..*.*(..))
  • @annotation("annotated class full name") expression case analysis
1) @annotation(com.annotation.RequiredCache),由RequiredCache注解描述的方法为缓存切入点方法
2) @annotation(com.annotation.RequiredLog),由RequiredLog注解描述的方法为日志切入点方法

AOP aspect priority setting analysis

When there are multiple aspects in the project, and corresponding to the same entry point, if the execution of the notification method in the aspect requires strict order requirements, we need to set the priority of the aspect at this time. This priority can be described by @Order (number priority) annotation, the smaller the number, the higher the priority. E.g:

Set the priority of the log aspect, the key code is as follows:

@Order(2)
@Aspect
@Component
public class SysLogAspect{
    
    }

To set the priority of the cached aspect, the key code is as follows:

@Order(1)
@Aspect
@Component
public class SysCacheAspect{
    
    }

If no priority is specified by default, the default is the lowest priority. Multiple slices under the same pointcut will form a slice chain.

Guess you like

Origin blog.csdn.net/weixin_40597409/article/details/113448864