preface
In the software industry, AOP is the abbreviation of Aspect Oriented Programming, which means: Aspect Oriented Programming, a technology that realizes the unified maintenance of program functions through precompiled mode and dynamic agent during operation. AOP is the continuation of OOP, a hot spot in software development, an important content of Spring framework and a derivative paradigm of functional programming. AOP can isolate all parts of business logic, so as to reduce the coupling between all parts of business logic, improve the reusability of programs, and improve the efficiency of development!
The role of AOP in Spring
Provide declarative service: allow users to customize aspects
Know the following proper nouns
- Crosscutting concerns: methods or functions that span multiple modules of an application. Even if it has nothing to do with our business logic, the part we need to focus on is crosscutting concerns! Eg: log, security, cache, etc
- Aspect: crosscutting concerns, special objects that are modularized, i.e. classes (log classes, security classes, etc.)
- Adive: the work that must be completed in all aspects, that is, the method of the class (the method of the log class and the method of the security class)
- Target: 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
- JointPoint: the execution point that matches the pointcut
In spring AOP, crosscutting logic is defined through advice. Spring supports 5 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.springframework.aop.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 |
Spring implements AOP
To use AOP weaving, you need to import a dependency package!
<dependencies> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.13.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.13.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.2.2.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> </dependencies>
1. Method 1: Spring API interface!
Case, print log!
Note that after we configure, the tool will give us a prompt, that is, the sign on the left of the code!
UserService interface!
-
public interface UserService { void add(); void delete(); void query(); void update(); }
UserServiceImpl
public class UserServiceImpl implements UserService { public void add() { System.out.println("Added a user information"); } public void delete() { System.out.println("Deleted a user information"); } public void query() { System.out.println("Queried a user information"); } public void update() { System.out.println("Updated a user information"); } }
The front log implements the MethodBeforeAdvice interface
public class PrevLog implements MethodBeforeAdvice { /* * @param method The method of the target object to execute * @param objects parameter * @param o Target object * @return void * @author Manon Tianyu * @date 2021/4/5 10:02 */ public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println("[PrevLog: ]" + new SimpleDateFormat("yyyy-MM-hh hh:mm:ss").format(new Date()) + o.getClass().getName() + "of" + method.getName() + "Executed"); } }
The post log implements the AfterReturningAdvice interface
public class AfterLog implements AfterReturningAdvice { /* * @param o Return results * @param method The method of the target object to execute * @param objects parameter * @param o1 Target object * @return void * @author Manon Tianyu * @date 2021/4/5 10:47 */ public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable { System.out.println("[AfterLog: ]" + new SimpleDateFormat("yyyy-MM-hh hh:mm:ss").format(new Date()) + "Yes" + method.getName() + "The returned result is" + o); } }
To configure bean s, we use the native configuration method! Here we will introduce aop constraint!
<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="userService" class="com.tian.aop.demo01interface.service.UserServiceImpl"/> <bean id="prevLog" class="com.tian.aop.demo01interface.log.PrevLog"/> <bean id="afterLog" class="com.tian.aop.demo01interface.log.AfterLog"/> <!-- Mode 1 native SpringAOP Interface --> <!-- to configure AOP:Import aop Constraints! --> <aop:config> <!-- breakthrough point - Where --> <!-- expression expression execution(Location to execute ) --> <aop:pointcut id="point" expression="execution(* com.tian.aop.demo01interface.service.UserServiceImpl.*(..))"/> <!-- Execute surround increase --> <aop:advisor advice-ref="prevLog" pointcut-ref="point"/> <aop:advisor advice-ref="afterLog" pointcut-ref="point"/> </aop:config> </beans>
Test!
public class Test { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("springApplicationContext.xml"); // Dynamic agent, the agent is the interface! UserService userService = context.getBean("userService", UserService.class); userService.add(); userService.delete(); userService.query(); userService.update(); } }
result!
[PrevLog: ]2021-04-10 10:45:27com. tian. aop. demo01. service. The add of userserviceimpl was executed
Added a user information
[afterlog:] 2021-04-10 10:45:27 executed add and returned null
[PrevLog: ]2021-04-10 10:45:27com. tian. aop. demo01. service. The delete of userserviceimpl was executed
Deleted a user information
[afterlog:] 2021-04-10 10:45:27 the delete was executed and the returned result was null
[PrevLog: ]2021-04-10 10:45:27com. tian. aop. demo01. service. The query of userserviceimpl was executed
Queried a user information
[afterlog:] 2021-04-10 10:45:27 the query was executed and the returned result was null
[PrevLog: ]2021-04-10 10:45:27com. tian. aop. demo01. service. The update of userserviceimpl was executed
Updated a user information
[afterlog:] 2021-04-10 10:45:27 the update was executed and the returned result was null
2. Method 2: implement AOP with user-defined classes
diy class
public class DiyPointCut { public void before(){ System.out.println("Before method execution"); } public void after(){ System.out.println("After method execution"); } }
Configuration bean
<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="userService" class="com.tian.aop.demo01interface.service.UserServiceImpl"/> <bean id="prevLog" class="com.tian.aop.demo01interface.log.PrevLog"/> <bean id="afterLog" class="com.tian.aop.demo01interface.log.AfterLog"/> <!-- Mode 2 customization --> <bean id="diy" class="com.tian.aop.demo02diy.service.DiyPointCut"/> <!-- to configure aop --> <aop:config> <!-- Customize the cutting plane and introduce the class to be cut --> <aop:aspect ref="diy"> <!-- breakthrough point --> <aop:pointcut id="point" expression="execution(* com.tian.aop.demo01interface.service.UserServiceImpl.*(..))"/> <!-- Notification at entry point id by point,implement before method --> <aop:before method="before" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config> </beans>
Test!
public class Test { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("springApplicationContext.xml"); // Dynamic agent, the agent is the interface! UserService userService = context.getBean("userService", UserService.class); userService.add(); userService.delete(); userService.query(); userService.update(); } }
result!
Before method execution
Added a user information
After method execution
Before method execution
Deleted a user information
After method execution
Before method execution
Queried a user information
After method execution
Before method execution
Updated a user information
After method execution
3. Method 3: implement AOP with annotation
Annotation implementation
@Aspect // Flag this class is a facet public class AnnotionPointCut { @Before("execution(* com.tian.aop.demo01interface.service.UserServiceImpl.*(..)))") public void before(){ System.out.println("Before method execution"); } @After("execution(* com.tian.aop.demo01interface.service.UserServiceImpl.*(..)))") public void after(){ System.out.println("Method after use"); } @Around("execution(* com.tian.aop.demo01interface.service.UserServiceImpl.*(..)))") public void arount(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("Surround front"); // Print signature is the method to execute! System.out.println(proceedingJoinPoint.getSignature()); // Execution method Object proceed = proceedingJoinPoint.proceed(); System.out.println("After surround"); } }
Configuration bean
<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="userService" class="com.tian.aop.demo01interface.service.UserServiceImpl"/> <bean id="prevLog" class="com.tian.aop.demo01interface.log.PrevLog"/> <bean id="afterLog" class="com.tian.aop.demo01interface.log.AfterLog"/> <!-- Mode 3 annotation implementation aop --> <bean id="annotion" class="com.tian.aop.demo03annotion.service.AnnotionPointCut"/> <!-- Enable annotation support Default is JDK(proxy-target-class="false") cglib(proxy-target-class="true") jdk and cglib There is no difference in the execution results! --> <aop:aspectj-autoproxy proxy-target-class="true"/> </beans>
result!
Surround front
void com.tian.aop.demo01interface.service.UserServiceImpl.add()
Before method execution
Added a user information
Method after use
After surround
Surround front
void com.tian.aop.demo01interface.service.UserServiceImpl.delete()
Before method execution
Deleted a user information
Method after use
After surround