9.1 what is AOP
AOP (Aspect Oriented Programming) means: Aspect Oriented Programming, which realizes the unified maintenance of program functions through precompiled mode and runtime dynamic agent. AOP is the continuation of OOP, a hot spot in software development, an important content in Spring framework, and a derivative paradigm of functional programming. AOP can isolate each part of business logic, reduce the coupling between each part of business logic, improve the reusability of program, and improve the efficiency of development.
9.2 role of AOP in Spring
Provide declarative transactions; Allows you to customize the cut plane
-
Crosscutting concerns: methods or functions that span multiple modules of an application. That is, the part that has nothing to do with our business logic, but we need to focus on is crosscutting concerns. Such as logging, security, caching, transactions, and so on
-
Aspect: a special object whose crosscutting concerns are modularized. That is, it is a class
-
Advice: work that must be completed in all aspects. That is, it is a method in a class
-
Target: the notified object
-
Proxy: an object created after notification is applied to the target object
-
PointCut: the definition of the "place" where the aspect notification is executed
-
Join point: the execution point that matches the pointcut
In spring AOP, crosscutting logic is defined through Advice. Spring supports five types of Advice
Notification type | Connection point | Implementation interface |
---|---|---|
Before advice | Before method | org.springframework.aop.MethodBeforeAdvice |
Post notification | After method | org.springframework.aop.AfterReturningAdvice |
Around Advice | Before and after method | org.aopalliance.intercept.MethodInterceptor |
Exception throw notification | Method throws an exception | org.springframework.aop.ThrowsAdvice |
Introduction notice | Add a new method attribute to the class | org.springframework.aop.IntroductionInterceptor |
That is, AOP adds new functions without changing the original code
9.3 using Spring to implement AOP
Using AOP weaving requires importing a dependency package
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency>
Premise Code:
UserService interface
public interface UserService { void add(); void delete(); void update(); void select(); }
UserServiceImpl
public class UserServiceImpl implements UserService{ public void add() { System.out.println("Add a new user"); } public void delete() { System.out.println("Delete a user"); } public void update() { System.out.println("Modify a user"); } public void select() { System.out.println("Query a user"); } }
- Method 1: use the Spring API interface
Pre Log
public class Log implements MethodBeforeAdvice { //Method: the method of the target object to execute //args: parameter //Target: target object public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName() + "of" + method.getName() + "Executed"); } }
Post Log
public class AfterLog implements AfterReturningAdvice { //returnValue: return value public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("Yes" + method.getName() + "Method, the return result is" + returnValue); } }
applicationContext.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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--register bean--> <bean id="userService" class="com.lrm.service.UserServiceImpl"/> <bean id="log" class="com.lrm.log.Log"/> <bean id="afterLog" class="com.lrm.log.AfterLog"/> <!--Method 1: use native Spring API Interface--> <!--to configure aop: Import required aop Constraints of--> <aop:config> <!--Entry point: expression: expression, execution(Return type package name.Class name.Method name(parameter))--> <aop:pointcut id="pointcut" expression="execution(* com.lrm.service.UserServiceImpl.*(..))"/> <!--Execute surround increase--> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config> </beans>
Test class
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //The dynamic proxy is the interface UserService userService = context.getBean("userService", UserService.class); userService.add(); } }
- Method 2: Customize to implement AOP
Custom pointcuts
public class DiyPointCut { public void before(){ System.out.println("=====Before method execution====="); } public void after(){ System.out.println("=====After method execution====="); } }
applicationContext.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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--register bean--> <bean id="userService" class="com.lrm.service.UserServiceImpl"/> <bean id="log" class="com.lrm.log.Log"/> <bean id="afterLog" class="com.lrm.log.AfterLog"/> <!--Method 2: user defined class--> <bean id="diy" class="com.lrm.diy.DiyPointCut"/> <aop:config> <!--Custom cut, ref Class to reference--> <aop:aspect ref="diy"> <!--breakthrough point--> <aop:pointcut id="point" expression="execution(* com.lrm.service.UserServiceImpl.*(..))"/> <!--notice--> <aop:before method="before" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config> </beans>
Test class
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //The dynamic proxy is the interface UserService userService = context.getBean("userService", UserService.class); userService.add(); } }
- Method 3: using annotations
Write annotation class
//Using annotation to implement aop @Aspect //Label this class as a facet public class AnnotationPointCut { @Before("execution(* com.lrm.service.UserServiceImpl.*(..))") public void before(){ System.out.println("=====Before method execution====="); } @After("execution(* com.lrm.service.UserServiceImpl.*(..))") public void after(){ System.out.println("=====After method execution====="); } //In surround enhancement, you can give a parameter that represents the point at which you want to get the processing pointcut @Around("execution(* com.lrm.service.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint point) throws Throwable { System.out.println("Surround front"); //Get signature Signature signature = point.getSignature(); System.out.println("signature: "+signature); //Execution method point.proceed(); System.out.println("After surround"); } }
applicationContext.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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--register bean--> <bean id="userService" class="com.lrm.service.UserServiceImpl"/> <bean id="log" class="com.lrm.log.Log"/> <bean id="afterLog" class="com.lrm.log.AfterLog"/> <!--Method 3: use annotation--> <bean id="annotationPointCut" class="com.lrm.anno.AnnotationPointCut"/> <!--Enable annotation support JDK(default proxy-target-class="false") cglib(proxy-target-class="true")--> <aop:aspectj-autoproxy/> </beans>
Test class
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //The dynamic proxy is the interface UserService userService = context.getBean("userService", UserService.class); userService.add(); } }