1 definition of AOP
AOP (Aspect Oriented Programming) means: Aspect Oriented Programming, which realizes the unified maintenance of program functions through precompiled mode and runtime dynamic agent.
Aspect oriented programming is a supplement to object-oriented programming. It encapsulates the parts commonly called by each business module generated by object-oriented programming to achieve the purpose of decoupling from the main business logic. At the same time, AOP can enhance the original functions without changing the original code. (agent mode, opening and closing principle)
2 AOP in spring
AOP is one of the features of Spring. It allows us to complete aspect oriented programming with a small amount of code.
Spring AOP is based on dynamic proxy. Currently, spring AOP supports JDK dynamic proxy and Cglib proxy.
AOP in Spring is defined as follows:
The meanings of core terms are as follows:
- Crosscutting concerns: the parts we need to focus on are crosscutting concerns;
- Facets: special objects whose crosscutting concerns are modularized. Is a class;
- Notice: work to be completed in section. Is a method in a class;
- Pointcut: the expression used to match a specific access point. Matching access points through pointcut expression is the core of AOP. Spring uses the pointcut expression of AspectJ by default;
- Weaving: link one or more facets with a class or object to create an enhanced object;
- Access point: a point during program execution, such as method execution, class initialization, exception handling.
Four Advice methods commonly used in Spring AOP:
Notification type | Connection point |
---|---|
Before advice | Before method execution |
Post notification | After the method is put back |
Around Advice | Before and after method |
Exception throw notification | Method threw an exception |
Let's experience the execution sequence of the same aspect and different advice:
For more information on the implementation process of notification, please see the great God's blog: [portal]
3 using Spring to implement AOP
3.1 implementation by using Spring API interface
1. Import the dependent packages required by AOP
<!-- Practice has proved that this code is really necessary to write --> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.encoding>UTF-8</maven.compiler.encoding> <java.version>11</java.version> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.9.RELEASE</version> </dependency> <!-- AOP Required dependent packages --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> </dependencies> <!-- Static resource export --> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> </build>
2 write the original business interface and implementation class
package sharm.service; public interface Rent { public void rent(); }
package sharm.service; public class Host implements Rent { @Override public void rent() { System.out.println("I'm the landlord. I want to rent the house."); } }
3 write two enhancement classes, one is pre enhancement and the other is post enhancement. That is, the section we need to weave in
3.1 pre enhancement
package sharm.log; import org.springframework.aop.MethodBeforeAdvice; import java.lang.reflect.Method; public class BeforeLog implements MethodBeforeAdvice { //Method: the method of the target object to execute //args: parameter of the called method //Target: target object @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName() + "of" + method.getName() + "Method was executed"); // Additional business areas seeHouse(); } //House viewing public void seeHouse(){ System.out.println("Show the tenant"); } }
3.2 post enhancement
package sharm.log; import org.springframework.aop.AfterReturningAdvice; import java.lang.reflect.Method; public class AfterLog implements AfterReturningAdvice { //returnValue: return value //Method: called method //args: parameter of the object of the called method //Target: the called target object @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("Yes" + target.getClass().getName() +"of"+method.getName()+"method," +"Return value:"+returnValue); // Additional business areas fare(); } // Intermediary fee public void fare(){ System.out.println("Intermediary fee"); } }
4 configure the Spring configuration file and implement AOP cut in
<?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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--register bean--> <bean id="host" class="sharm.service.Host"/> <bean id="beforeLog" class="sharm.log.BeforeLog"/> <bean id="afterLog" class="sharm.log.AfterLog"/> <!--aop Configuration of--> <aop:config> <!--breakthrough point expression:The expression matches the method to execute--> <aop:pointcut id="pointcut" expression="execution(* sharm.service.*.*(..))"/> <!--Execution notice. advice-ref: Execution method, pointcut-ref breakthrough point--> <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config> </beans>
In the pointcut expression execution(* sharm.service. * * (..) In, the meaning of each parameter is as follows:
-
execution() represents the body of the expression;
-
The first * indicates that the return type is all types;
-
sharm.service. Indicates the package name. One point in the tail represents the current package, and two points represent all sub packages under the current package;
-
The second * indicates that the class name is all classes;
-
*(..) The asterisk in represents all methods, the parentheses behind represent the parameters of the method, and the two periods represent any parameters.
5 write test class
import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import sharm.service.Rent; public class AopTest { @Test public void myTest(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // The implementation class is used in the Bean, and the return value adopts the interface Rent hostService = (Rent)context.getBean("host"); hostService.rent(); } }
6 control panel output
3.2 implementation through user-defined classes
1. Import the dependent packages required by AOP
2 write the original business interface and implementation class
3. Implement AOP by customizing the cut in class
package sharm.log; public class CustomAspect { //House viewing public void seeHouse(){ System.out.println("Show the tenant"); } // Intermediary fee public void fare(){ System.out.println("Intermediary fee"); } }
4. Configuring Spring is very critical
<!--register bean--> <bean id="host" class="sharm.service.Host"/> <bean id="customAspect" class="sharm.log.CustomAspect"/> <!--aop Configuration of--> <aop:config> <!--The second way: use AOP Label Implementation of--> <aop:aspect ref="customAspect"> <aop:pointcut id="customPointCut" expression="execution(* sharm.service.*.*(..))"/> <aop:before pointcut-ref="customPointCut" method="seeHouse"/> <aop:after pointcut-ref="customPointCut" method="fare"/> </aop:aspect> </aop:config>
6 write test classes
7 control panel output
3.3 using annotations to implement
1. Import the dependent packages required by AOP
2 write the original business interface and implementation class
3 write an enhanced class for annotation implementation
package sharm.log; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class AnnotationAspect { //House viewing @Before("execution(* sharm.service.*.*(..))") public void seeHouse(){ System.out.println("Show the tenant"); } @After("execution(* sharm.service.*.*(..))") // Intermediary fee public void fare(){ System.out.println("Intermediary fee"); } }
4 register bean s in the Spring configuration file and add configurations that support annotations
<!--register bean--> <bean id="host" class="sharm.service.Host"/> <!--The third way:Annotation implementation--> <bean id="annotationPointcut" class="sharm.log.AnnotationAspect"/> <aop:aspectj-autoproxy/>
Through the < aop: aspectJ AutoProxy / > declaration of the aop namespace, automatically create a proxy for those bean s configured with the @ aspectJ aspect in the spring container and weave the aspect in. Of course, spring still uses AnnotationAwareAspectJAutoProxyCreator internally to create automatic proxy, but the specific implementation details have been hidden by < aop: aspectJ AutoProxy / >
< AOP: AspectJ AutoProxy / > has a proxy target class attribute, which is false by default, indicating that jdk dynamic proxy is used for weaving enhancement. When it is configured as < AOP: AspectJ AutoProxy poxy target class = "true" / /, it indicates that CGLib dynamic proxy technology is used for weaving enhancement. However, even if proxy target class is set to false, if the target class does not declare an interface, spring will automatically use CGLib dynamic proxy.
5 write test class
6 control panel output