Article catalog*
Spring framework learning notes 05: Spring AOP Basics
1, Spring AOP
(1) Basic meaning of AOP
AOP (Aspect oriented programming) can be said to be the supplement and improvement of OOP (object-oriented programming). OOP introduces the concepts of encapsulation, inheritance and polymorphism to establish an object hierarchy to simulate a set of public behaviors. When we need to introduce public behavior for decentralized objects, OOP is powerless. In other words, OOP allows you to define the relationship from top to bottom, but it is not suitable for defining the relationship from left to right. For example, log function. Log code is often spread horizontally across all object levels, regardless of the core functions of the objects it spreads. The same is true for other types of code, such as security, exception handling, and transparent persistence. This kind of irrelevant code scattered everywhere is called cross cutting code. In OOP design, it leads to a large number of code duplication, which is not conducive to the reuse of each module. On the contrary, AOP technology uses a technology called "crosscutting" to dissect the interior of encapsulated objects, encapsulate the public behaviors that affect multiple classes into a reusable module, and call it "Aspect", that is, Aspect. The so-called "Aspect", in short, is to encapsulate the logic or responsibilities that have nothing to do with the business but are jointly invoked by the business modules, so as to reduce the repeated code of the system, reduce the coupling degree between modules, and facilitate the operability and maintainability in the future. AOP represents a horizontal relationship. If an "object" is a hollow cylinder, it encapsulates the attributes and behavior of the object; Then the Aspect oriented programming method is like a sharp blade to cut open these hollow cylinders to obtain their internal messages. The cut section is the so-called "Aspect". Then it restored these cut sections without leaving any trace with its skillful hand of seizing heavenly power.
(2) Basic role of AOP
-
Software development principle: high cohesion, low coupling
-
Spring's AOP function is decoupling. AOP allows a group of classes to share the same behavior (such as transaction management, log management, security management).
-
OOP (object oriented programming) can only increase the coupling degree of code by inheriting classes or implementing interfaces, and class inheritance is single root inheritance (one child and multiple parents are not allowed), which hinders adding more behaviors to a group of classes. At this time, AOP can make up for the deficiency of OOP.
Mission: before and after the knight's mission, the Bard sings a hymn
(1) Implemented in traditional way
- Modify brave knight class
- Modify beauty saving Knight class
- Execute test class - TestKnight
(2) Disadvantages of traditional implementation
- The embarkOnQuest() method of each Knight class needs to be modified. The coupling degree is too high. When the number of Knight classes is large, the task is very boring and cumbersome.
Next, we use AOP to realize the same function. Through comparison, we can better understand the advantages of AOP.
2, Use AOP in configuration mode
(1) Create package
- In net wh. Create lesson05 in the spring package aop_ XML subpackage
(2) Create dragon killing task class
- In AOP_ Create dragon killing task class in XML sub package - SlayDragonQuest
(3) Create brave knight class
- In AOP_ Create brave knight class in XML sub package - BraveKnight
(4) Create the human of poetry
- In AOP_ Create Minstrel human in XML sub package
(5) Create Spring configuration file
- Create AOP in resources_ XML directory and create spring config. XML in it 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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--Component scan--> <context:component-scan base-package="net.wh.spring.lesson05.aop_xml"/> <!--AOP to configure--> <aop:config> <!--Define section--> <aop:aspect ref="minstrel"> <!--Define tangent point--> <aop:pointcut id="embark" expression="execution(* net.wh.spring.lesson05..*.embarkOnQuest(..))"/> <!--Declaration pre notice--> <aop:before method="singBeforeQuest" pointcut-ref="embark"/> <!--Post declaration notification--> <aop:after method="singAfterQuest" pointcut-ref="embark"/> </aop:aspect> </aop:config> </beans>
1. Tangent point
- When configuring AOP using the Spring framework, pointcut needs to be defined whether through XML configuration file or annotation.
2. Tangent expression
-
Specified method in interception class:"execution(* net.hw.spring.lesson05..*.embarkOnQuest(..))"
-
Intercept all methods in the class:"execution(* net.hw.spring.lesson05..*.*(..))"
3. Tangent function
execution() is the most commonly used tangent function. The whole expression can be divided into five parts.
- execution(): expression body.
- The first * * indicates the return type, and the '' indicates all types.
- Package name: indicates the name of the package to be intercepted. The following two periods represent the current package and all sub packages of the current package. Net hw. spring. Methods of all classes under lesson05 package and descendant package.
- The second * * indicates the class name, and the "" indicates all classes.
- **(...): the last asterisk represents the method name, the '' sign represents all methods, the following parentheses represent the parameters of the method, and the two periods represent any parameters.
(6) Add AOP related dependencies in pom file
<!--Spring AOP--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <!--AspectJ support--> <dependency> <groupId>aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.5.4</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.6</version> <scope>runtime</scope> </dependency>
(7) Create test class - TestKnight
Create net in test/java wh. spring. lesson05. aop_ XML package. Create TestKnight in the package
package net.wh.spring.lesson05.aop_xml; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestKnight { private ClassPathXmlApplicationContext context; // Application container based on classpath XML configuration file @Before public void init() { // Creating application container based on Spring configuration file context = new ClassPathXmlApplicationContext("aop_xml/spring-config.xml"); } @Test public void testBraveKnight() { // Gets the object from the application container by name BraveKnight braveKnight = (BraveKnight) context.getBean("Mike"); // Brave knight on mission braveKnight.embarkOnQuest(); } @After public void destroy() { // Close the application container context.close(); } }
Run the test method and view the test results
(9) Classroom practice
1. Add beauty saving task class and beauty saving Knight class
-
Write the method of the rescuedmselquest class
package net.wh.spring.lesson05.aop_xml; import org.springframework.stereotype.Component; @Component public class RescueDamselQuest { public void embark() { System.out.println("Perform the task of saving the United States."); } }
-
Write the method of DamselRescuingKnight class
package net.wh.spring.lesson05.aop_xml; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class DamselRescuingKnight { @Autowired private RescueDamselQuest rescueDamselQuest; public void embarkOnQuest() { rescueDamselQuest.embark(); } }
2. Add a test method - testDamselRescuingKnight() in the test class
-
Run the test method testDamselRescuingKnight()
3, Using AOP with annotations
(1) In net wh. Create lesson05.0 in the spring package aop_ Annotation sub package
(2) Create dragon killing task class
- In AOP_ Create a dragon killing task class in the annotation sub package - SlayDragonQuest
(3) Create brave knight class
- In AOP_ Create a brave knight class in the annotation sub package - BraveKnight
(4) Create a bard profile
- In AOP_ Create a bard aspect in the annotation sub package - minstrel aspect
package net.wh.spring.lesson05.aop_annotation; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect // Declare as slice @Component // Leave it to Spring container management public class MinstrelAspect { // Annotation declaration pointcut @Pointcut("execution(* net.wh.spring.lesson05..*.embarkOnQuest(..))") public void embark() { } // Annotation declaration pre notification @Before("embark()") public void singBeforeQuest(JoinPoint joinPoint) { System.out.println("La La, the knight is off!"); } // Post annotation notification @After("embark()") public void singAfterQuest(JoinPoint joinPoint) { System.out.println("Great! The knight has completed the task!"); } }
(5) Create Spring configuration class
- In AOP_ Create the Spring configuration class - AopConfig in the annotation sub package
package net.wh.spring.lesson05.aop_annotation; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration // Indicates the Spring configuration class @ComponentScan("net.wh.spring.lesson05.aop_annotation") // Component scan @EnableAspectJAutoProxy // Enable Spring support for AspectJ public class AopConfig { }
(6) Create Knight test class
- In test / Java / AOP_ Create a test class in the annotation sub package - TestKnight
package net.wh.spring.lesson05.aop_annotation; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class TestKnight { private AnnotationConfigApplicationContext context; // Application container based on annotation configuration class @Before public void init() { // Create application container based on annotation configuration class context = new AnnotationConfigApplicationContext(AopConfig.class); } @Test public void testBraveKnight() { // Get the object from the application container by name BraveKnight knight = (BraveKnight) context.getBean("Mike"); // Brave knight on mission knight.embarkOnQuest(); } @After public void destroy() { // Close the application container context.close(); } }
- Run the test and view the test results
(7) Classroom practice
1. Add beauty saving task class and beauty saving Knight class
- Beauty rescue task
package net.wh.spring.lesson05.aop_annotation; import org.springframework.stereotype.Component; @Component public class RescueDamselQuest { public void embark() { System.out.println("Perform the task of saving the United States."); } }
- Beauty saving Knights
package net.wh.spring.lesson05.aop_annotation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class DamselRescuingKnight { @Autowired private RescueDamselQuest rescueDamselQuest; public void embarkOnQuest() { rescueDamselQuest.embark(); } }
2. Add the test method of saving American knight in the test class - testDamselRescuingKnight()
3. Run the testDamselRescuingKnight() method to see the results
4, Implement annotated interception
(1) Meaning of interception
Intercepting a method before it is accessed and adding some operations before or after the method is executed is actually an implementation strategy of AOP. Spring provides an Interceptor, which allows developers to define the code to be executed before and after an action is executed by dynamically intercepting the object called by the action, and can also prevent the execution of an action before it is executed. It also provides a way to extract reusable parts of actions. In this case, we learn annotated interception without interceptors.
(2) Create annotation interface
stay aop_annotation Create annotation interface in sub package - Action
package net.wh.spring.lesson05.aop_annotation; import java.lang.annotation.*; @Target(ElementType.METHOD) // Intercept target - Method @Retention(RetentionPolicy.RUNTIME) // Retention policy - runtime @Documented // Annotation documentation public @interface Action { String name(); }
1. @ Target({ElementType.TYPE}) annotation
ElementType Constants of this enumeration type provide a simple classification: annotations may appear in Java Syntax position in the program (these constants and meta annotation types)(@Target)Specify where to write the annotation together (legal location)
2. @ Retention({RetentionPolicy.Runtime}) annotation
RetentionPolicy Constants of this enumeration type describe various strategies for retaining annotations, which are similar to meta annotations(@Retention)Specify how long to keep the comment together
3. @ Documented annotation
Documented The annotation indicates that this annotation is made by javadoc A similar recording tool is available by default. If a type declaration is annotated and documented, its annotation becomes public API Part of.
(3) Modify brave knight class
- Add a custom annotation Action to embarkOnQuest() and set its name attribute
(4) Modify bard profile
package net.wh.spring.lesson05.aop_annotation; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import java.lang.reflect.Method; @Aspect // Declare as slice @Component // Leave it to Spring container management public class MinstrelAspect { // Annotation declaration pointcut // Annotation declaration pointcut @Pointcut("@annotation(net.wh.spring.lesson05.aop_annotation.Action)") public void embark() { } // Annotation declaration pre notification @Before("embark()") public void singBeforeQuest(JoinPoint joinPoint) { // Get method signature MethodSignature signature = (MethodSignature) joinPoint.getSignature(); // Get intercepted method Method method = signature.getMethod(); // Get annotated intercept Action action = method.getAnnotation(Action.class); // Prompt that the user is blocked System.out.println("[" + action.name() + "]Intercepted[" + method.getName() + "]: Before interception!"); System.out.println("La La, the knight is off!"); } // Post annotation notification @After("embark()") public void singAfterQuest(JoinPoint joinPoint) { // Get method signature MethodSignature signature = (MethodSignature) joinPoint.getSignature(); // Get intercepted method Method method = signature.getMethod(); // Get annotated intercept Action action = method.getAnnotation(Action.class); // Prompt that the user is blocked System.out.println("[" + action.name() + "]Intercepted[" + method.getName() + "]: Before interception!"); System.out.println("Great! The knight has completed the task!"); } }
(5) Run the test method testBraveKnight() to see the effect
(6) Modify the beauty saving Knight class and add a custom annotation Action to embarkOnQuest()
(7) Run the test method testDamselRescuingKnight() to see the effect
(8) Classroom practice
Task: output the time taken by the knight to complete the task
-
Create time consuming aspect class - ElapseAspect
-
package net.wh.spring.lesson05.aop_annotation; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import java.lang.reflect.Method; import java.util.Date; @Aspect // Declare as slice @Component // Leave it to Spring container management public class ElapseAspect { public int SartTime; public int EndTime; // Annotation declaration pointcut @Pointcut("@annotation(net.wh.spring.lesson05.aop_annotation.Action)") public void embark() { } @Before("embark()") public void singBeforeQuest() { SartTime = (int) new Date().getTime(); } @After("embark()") public void singAfterQuest() { EndTime = (int) new Date().getTime(); int a = EndTime-SartTime; System.out.println("Task time:"+a+"millisecond"); } }
-
Run the test method testBraveKnight() to see the effect
- Run the test method testDamselRescuingKnight() to see the effect
- Let only the time-consuming section work, and view the operation results
public void embark() {
}
@Before("embark()")
public void singBeforeQuest() {
SartTime = (int) new Date().getTime();
}
@After("embark()") public void singAfterQuest() { EndTime = (int) new Date().getTime(); int a = EndTime-SartTime; System.out.println("Task time:"+a+"millisecond"); }
}
- Run test method testBraveKnight(),View effect [External chain picture transfer...(img-CQ9d8twn-1625547111632)] - Run test method testDamselRescuingKnight(),View effect [External chain picture transfer...(img-8raUEyTw-1625547111633)] - Let only the time-consuming section work, and view the operation results 