Spring learning: AOP operation

Posted by chmpdog on Sat, 12 Feb 2022 14:50:16 +0100

1, AOP operational terminology

1. Connection point

The methods in the class that can be enhanced are called join points.

2. Entry point

The method that is actually really enhanced is called the entry point.

3. Notification (enhanced)

(1) The logical part of the actual enhancement is called notification (enhancement)

(2) There are several types of notifications, as follows:

  • Before advice
  • Post notification
  • Around Advice
  • Exception notification
  • Final notice

4. Section

Aspect is an action, which refers to the process of applying notifications to pointcuts, which is called aspect.

2, AOP operation

Spring frameworks generally implement AOP operations based on AspectJ. AspectJ is not a part of spring, but an independent AOP framework. Generally, AspectJ and Spirng framework are used together for AOP operation.

There are two ways to implement AOP operation based on AspectJ:

  • Implementation of configuration file based on xml
  • Annotation based implementation (use)

2.1 pointcut expression

Function of pointcut expression: know which method in which class to enhance. The syntax structure is as follows:

execution([permission modifier] [return type] [class full path] [method name] ([parameter list]))

As shown in the figure below:

 

An example of writing tangent points is as follows:

 1. As for com wyf. spring5. If add in the book class is enhanced, the pointcut expression is as follows:

execution(* com.wyf.spring5.Book.add(..))

2. For example, com wyf. spring5. All method enhancements in the book class:

execution(* com.wyf.spring5.Book.*(..))

3. For example, on www wyf. All classes and methods in the spring 5 package are enhanced

execution(*  com.wyf.spring5.*.* (..)) 

2.2 AOP operation (AspectJ annotation method)

1) first, we create a class and add a method:

/**
 * Enhanced class
 */
public class User {
    public void add(){
        System.out.println("add*****");
    }
}

2) Then we create enhancement classes (write enhancement logic)

  • Create methods in the enhanced class so that different methods represent different notification types
/**
 * Enhancement class
 */
public class UserProxy {
    /**
     * Pre notification logic
     */
    public void before(){
        System.out.println("before*****");
    }
}

3) Configure notifications

  • In the spring configuration file, turn on annotation scanning. (implemented by java configuration class or xml configuration file)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- Enable annotation scanning -->
    <context:component-scan base-package="com.wyf.aopanno"></context:component-scan>

    <!-- open Aspect Generate proxy object -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
</beans>
  • Create User and UserProxy objects with annotations (add the annotation of creating object above the class, here @ Component)
  • Add the annotation @ Aspect on the enhanced class
/**
 * Enhanced class
 */
@Component
public class User {
    public void add(){
        System.out.println("add*****");
    }
}

/**
 * Enhancement class
 */
@Component
@Aspect  //Generate proxy object
public class UserProxy {
    /**
     * Pre notification logic
     */
    public void before(){
        System.out.println("before*****");
    }
}
  • Turn on the generation proxy object in the spring configuration file
    <!-- open Aspect Generate proxy object -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

Enabling Aspect to generate a proxy object is equivalent to scanning the class with @ Aspect annotation and generating a proxy object of the object.

4) Configure different types of notifications

In the enhanced class, add a notification type annotation on the notification method and use the pointcut expression configuration.

/**
 * Enhancement class
 */
@Component
@Aspect  //Generate proxy object
public class UserProxy {
    /**
     * Pre notification logic
     */
    //@The Before annotation indicates that it is used as a pre notification
    //The pointcut expression specifies which method of which class the notification is enhanced for.
    @Before(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void before(){
        System.out.println("before*****");
    }
}

The test code is as follows:

    @Test
    public void TestAop(){
        //1. Load spring configuration file
        ApplicationContext context = new ClassPathXmlApplicationContext("beanAop1.xml");
        //Get object
        User user = context.getBean("user",User.class);
        user.add();
    }

Execution result:

The previous article only gives the code of pre notification @ Before, and the following gives the example code of all five notifications to complete all the notifications in the above example.

/**
 * Enhancement class
 */
@Component
@Aspect  //Generate proxy object
public class UserProxy {
    /**
     * Pre notification logic
     */
    //@The Before annotation indicates that it is used as a pre notification
    //The pointcut expression specifies which method of which class the notification is enhanced for.
    @Before(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void before(){
        System.out.println("before*****");
    }
    /**
     * Post notification (return notification)
     */
    @AfterReturning(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void afterReturning(){
        System.out.println("afterReturning*****");
    }
    /**
     * The final notification will be executed even if there are exceptions
     */
    @After(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void after(){
        System.out.println("after*****");
    }
    /**
     * Exception notification
     */
    @AfterThrowing(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void afterthrowing(){
        System.out.println("afterthrowing*****");
    }
    /**
     * Surround notification, both before and after the method
     */
    @Around(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("Before surround*****");
        //Perform enhanced methods
        proceedingJoinPoint.proceed();
        System.out.println("After surround*****");
    }

The code execution results are as follows:

Among them, after is executed after the enhanced method, and after returning is executed after the return value of the method.

2.3 extraction of the same entry point

In the above example, we have written five kinds of notifications put by the enhanced party, namely pre notification, post notification, exception notification, final notification and surround notification. When writing the enhanced class, we use the pointcut expression in the notification annotation to indicate which method of which class is to be enhanced by the notification. However, we will find that when we enhance the same method, its pointcut expression is the same. In order to avoid repetition, we can extract the same pointcut.

In the following example, we extract the same Pointcut with @ Pointcut, and the code is as follows:

    //Extract the same pointcut
    @Pointcut(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void pointdemo(){
    }

When we want to use the pointcut expression elsewhere, we can directly use its method name. As follows:

/**
 * Enhancement class
 */
@Component
@Aspect  //Generate proxy object
public class UserProxy {

    //Extract the same pointcut
    @Pointcut(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void pointdemo(){
    }

    /**
     * Pre notification logic
     */
    //@The Before annotation indicates that it is used as a pre notification
    //The pointcut expression specifies which method of which class the notification is enhanced for.
    @Before(value = "pointdemo()")
    public void before(){
        System.out.println("before*****");
    }
    /**
     * Post notification (return notification)
     */
    @AfterReturning(value = "pointdemo()")
    public void afterReturning(){
        System.out.println("afterReturning*****");
    }
}

2.4 multiple enhancement classes enhance the same method and set the priority of enhancement classes

If we now have another enhanced class, which also contains a before() method, we will also pre enhance the add() method of the enhanced class User. So how do we set the order of enhancement?

We add the annotation @ order (numeric type value) on the enhanced class. The smaller the numeric type value, the higher the priority, so as to ensure the enhanced sequential search. The code is as follows:

@Component
@Aspect
@Order(2)
public class PersonProxy {
    //Before advice 
    @Before(value = "execution(* com.wyf.aopanno.User.add(..))")
    public void before(){
        System.out.println("Person Before****");
    }
}

3, End

This paper mainly introduces the key sub of AOP and AOP operation based on annotation. Through an example, it introduces the pre notification, post notification, exception notification, final notification and surround notification of AOP.

Topics: Java Spring