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.