Spring AOP
Aspect oriented programming aims to encapsulate those operations that have nothing to do with business but are common to business modules (such as logging), so as to reduce system duplication of code and reduce system coupling.
Application scenario:
-
Logging
-
Permission control
-
transaction management
Underlying implementation principle
-
JDK dynamic proxy -- the premise is that the class implements the interface
-
CGLIB agent
Relationship between Spring AOP and AspectJ
-
Both are to implement AOP, which is based on dynamic proxy, and AspectJ is based on bytecode operation
-
AOP is a runtime enhancement
-
AspectJ is a compile time enhancement
If there are not many facets, there is not much performance difference between the two
AspectJ will be much faster if there are many facets
Some concepts in AOP
notice
When and what to do during method execution
- Pre Notification - operations to be performed before method execution
- Post Notification - action to be performed after method execution
- Return Notification - the operation to be performed after the method is successfully executed
- Exception Notification - the operation to be performed after a method throws an exception
- Surround Notification - custom operations should be performed before and after method execution
Connection point
It can be when a method is called or after an exception is thrown. It is always the front and back of the method. It is the connection point
breakthrough point
If a class has 10 methods, then there are 10 pointcuts
section
The combination of notification and entry point. In popular terms, notification indicates when to do + what to do, and entry point indicates where to do
illustrate
In order to explain the concept of AOP more conveniently, here is an example in life
It can be seen that the main business of the chartering company is to sign contracts and collect rent. That's enough. The parts framed in purple are all repetitive things. Just give them to the intermediary.
This is the idea of AOP: separation of core business code and focus code
Actual code
You can't just talk but practice. Let's experience the actual code
XMl based Demo
1. import dependency
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.7.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.5</version> </dependency> </dependencies>
2. create a Landlord class under the pojo package (Landlord ≈ charterer)
package jay.pojo; import org.springframework.stereotype.Component; /** * @author Jaychan * @date 2020/7/10 * @description TODO */ @Component("landlord") public class Landlord { public void service(){ //Only core business functions are realized System.out.println("Sign a contract"); System.out.println("Rent collection"); } }
3. create a Broker class (intermediary) under the aspect package
package jay.aspect; 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; @Component @Aspect class Broker { //Tell spring how to intercept //A cut-off point is customized to reduce the number of expressions and avoid code redundancy @Pointcut("execution(* jay.pojo.Landlord.service())") public void lService() { } @Before("lService()") public void before() { System.out.println("Show the tenant"); System.out.println("Talk about price"); } @After("lService()") public void after() { System.out.println("Turnkey"); } }
4. in applicationcontext Configure automatic injection in XML to tell ioc container where to scan these two bean s
<?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"> <context:component-scan base-package="aspect" /> <context:component-scan base-package="pojo" /> <aop:aspectj-autoproxy/> </beans>
5. writing test classes
package test; import org.springframework.context.support.ClassPathXmlApplicationContext; import pojo.Landlord; /** * @author Jaychan * @date 2020/7/10 * @description TODO */ public class TestSpring { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Landlord landlord = context.getBean("landlord", Landlord.class); landlord.service(); } }
6. operation results
July 10, 2020 3:19:52 afternoon org.springframework.context.support.AbstractApplicationContext prepareRefresh information: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@23ab930d: startup date [Fri Jul 10 15:19:52 CST 2020]; root of context hierarchy July 10, 2020 3:19:52 afternoon org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions information: Loading XML bean definitions from class path resource [applicationContext.xml] Show the tenant Talk about price Sign a contract Rent collection Turnkey Process finished with exit code 0
Annotation based Demo
Step 1: select the connection point
Spring is a method level AOP framework that can be specific to a method of a class as a connection point. Another way is to choose which method of that kind to enhance the function.
@Component("landlord") public class Landlord { public void service(){ //Only core business functions are realized System.out.println("Sign a contract"); System.out.println("Rent collection"); } }
We choose Landlord's service() method as the connection point
Step 2: create cut plane
After selecting the connection point, you can create the section. We can understand the aspect as an interceptor. When the program runs to the connection point, it will be intercepted. An initialization method will be executed at the beginning and a destruction method will be added at the end.
In Spring, as long as you annotate a class with * * @Aspect**, the SpringIoc container will consider this as an Aspect. At the same time, remember to add the @component tag to the Spring Ioc container.
package jay.aspect; 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; @Component @Aspect class Broker { @Pointcut("execution(* jay.pojo.Landlord.service())") public void lService() { } @Before("lService()") public void before() { System.out.println("Show the tenant"); System.out.println("Talk about price"); } @After("lService()") public void after() { System.out.println("Turnkey"); } }
Step 3: define the tangent point
The above annotation defines the regular expression of execution. Spring uses this regular expression to determine which method of which class to intercept:
execution(* jay.pojo.Landlord.service())
Analyze this expression in turn:
execution: triggered when the method is executed
*: method representing any return type
Jay Pojo Landlord: the fully qualified name of the representative class
service(): name of the intercepted method
Step 4: write the aopconfig configuration class
The main functions of this class are
Using JDK dynamic proxy
Tell the SpringIoc container to scan the classes under that package
@Configuration @ComponentScan("jay") @EnableAspectJAutoProxy //(proxyTargetClass = true) //If true, the cglib implementation will be used public class AopConfig { }
Step 5: write a test class
package jay; import jay.config.AopConfig; import jay.pojo.Landlord; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * @author Jaychan * @date 2020/7/10 * @description TODO */ public class TestSpring { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class); Landlord bean = context.getBean(Landlord.class); bean.service(); } }
Output results
July 10, 2020 3:26:13 afternoon org.springframework.context.support.AbstractApplicationContext prepareRefresh information: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2d38eb89: startup date [Fri Jul 10 15:26:13 CST 2020]; root of context hierarchy Show the tenant Talk about price Sign a contract Rent collection Turnkey Process finished with exit code 0