1. The whole process of Aop is Aspect Oriented Programming, which is a technology for facet-oriented programming, to achieve the same maintenance of program functions through pre-compilation and run-time dynamic agents.Aop is the continuation of oop, a hot spot in software development, and an important content in Spring framework.It is a derived example of functional programming, which can be used to split parts of business logic with Aop, thus reducing the coupling between parts of business logic, improving the reusability of programs, and improving development efficiency.Simply put, it is to extract duplicate code from our program and enhance it by using dynamic proxy technology and existing methods without modifying the source code when it needs to be executed.
Related Terms
JoinPoint: Link points Those that are intercepted refer to methods in spring because spring only supports connection points of method type
Pointcut: The entry point is the definition of which JoinPont s we want to intercept
Advice: Notification/Enhancement Notification is what you do after intercepting a Joinpoint
Notification Type: Pre Notification, Post Notification, Exception Notification, Final Notification, Surround Notification
Introduction: Introduction is a special notification that Introductions can dynamically add methods or field s to a class at run time without modifying its class code
Target: Target object, target object of proxy
Weaving weaving is the process of applying enhancements to target objects to create new proxy objects. spring uses dynamic proxy weaving, AspectJ uses compile-time weaving and class-loading weaving
Proxy: Proxy, a result proxy class produced when a class is enhanced by Aop weaving
Aspect: Aspect is the combination of entry point and notification (introductory)
In spring, the framework decides which dynamic proxy method to use based on whether the target class implements an interface or not.
XMl-based AOP steps
1. Create a Maven project to introduce spring coordinates
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mingqi</groupId> <artifactId>SpringIOC</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.7</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> </project>
2. Create business-tier interfaces:
package com.mingqi.services; public interface IAccountService { /** * Simulate login account */ void saveAccount(); /** * Simulate account updates * @param id */ void updateAccount(int id); /** * Simulate account deletion * @return */ int deleteAccount(); }
3. Create Business Tier Implementation Class
package com.mingqi.services.impl; import com.mingqi.services.IAccountService; public class AccountServicesImpl implements IAccountService { public void saveAccount() { System.out.println("Save performed"); } public void updateAccount(int id) { System.out.println("Update performed"+id); } public int deleteAccount() { System.out.println("Delete performed"); return 0; } }
4. Create Tool Class
package com.mingqi.utils; import org.aspectj.lang.ProceedingJoinPoint; /** * Tool class for user logging, which provides common code */ public class Logger { /** * For printing logs: plan for them to execute before the entry point method is executed (the entry point method is the business layer method) */ public void beforePrintLog(){ System.out.println("Logger In class pringLog Method started logging."); } public void afterReturningPrintLog() { System.out.println("after returning advise Logger In class beforePrintLog Method started logging."); } /** * Exception Notification */ public void afterThrowingPrintLog() { System.out.println("Exception Notification Logger In class afterThrowingPrintLog Method started logging."); } /** * Final Notification */ public void afterPrintLog() { System.out.println("Final Notification Logger In class afterPrintLog Method started logging."); } /** * Around Advice * Problem When we configured the surround notification, the entry point method did not execute and the notification method executed * Analysis: By comparing the surround notification codes in the dynamic proxy, we found that surround notifications in the dynamic proxy have explicit entry point method calls, but not in our code. * Solution: The Spring framework provides us with an interface: ProceedingJoinPoint.The interface has a method proceed(), which is equivalent to explicitly calling the method of the entry point * This interface can be used as a parameter method to surround notifications, and the spring framework provides us with implementation classes for this interface to use when the program executes * spring Surround notifications in * He's one of the ways the spring framework gives us manual control over when enhancements will execute in code * @param pjp * @return */ public Object aroundPringLog(ProceedingJoinPoint pjp){ Object rtValue = null; try{ Object[] args = pjp.getArgs();//Get the parameters required for method execution System.out.println("Logger In class aroundPringLog Method started logging.Front"); rtValue = pjp.proceed(args);//Explicitly invoke business tier methods (entry point methods) System.out.println("Logger In class aroundPringLog Method started logging.Rear"); return rtValue; }catch (Throwable t){ System.out.println("Logger In class aroundPringLog Method started logging.abnormal"); throw new RuntimeException(t); }finally { System.out.println("Logger In class aroundPringLog Method started logging.Final"); } } }
4. Create a bean 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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--Configure spring's IOC and service objects in it--> <bean id="accountSevice" class="com.mingqi.services.impl.AccountServicesImpl"></bean> <!-- xml-based OP configuration steps in spring 1. Give the notification beans to spring to manage 2. Use aop:config tag table name to start AOP configuration 3. UseAop:aspectLabel indicates configuration facet id property: is to provide a unique identification for the facet ref attribute: is the id of the specified notification class 4. InAop:aspectInside the label, use the corresponding label to configure the type of notification Our example now is to have the printlog method execute before the entry point method executes, so it is a pre-notification aop:before: Identify pre-notifications Method property: Used to specify which method in the Logger class is a pre-notification pointcut property: Used to specify an entry point expression that means which enhancements are made to methods in the business tier Writing of the entry point expression: Keyword: execution Expression: Access modifier return value package name. Package name. Package name.... Class name. Method name (parameter list) Standard writing: public voidCom.mingqi.service.Impl.AccountServiceImpl.saveAccount() Access modifiers can be omitted:voidCom.mingqi.service.Impl.AccountServiceImpl.saveAccount() Return values can use wildcards to identify any return value: *com.mingqi.service.impl.AccountServiceImpl.saveAccount() Package names can use wildcards to represent any package, but several levels of packages require writing * *. *. *.AccountServiceImpl.saveAccount() Package names can be used..To represent the current package and its subpackages: * *.AccountServiceImpl.saveAccount() Both class and method names can use * to achieve uniformity *. *. *(); Parameter list: You can write data types directly: The base type writes the name directly: int Write package names by reference type. How class names are written:java.lang.String Wildcards can be used to identify any type, only parameters are required You can use..To identify whether parameters are available or not, and parameters can be of any type Full wildcard writing: * *..*.*(..) A common way to write entry point expressions in real-world development: Cut to all methods of the business tier implementation class,*com.mingqi.service.impl. *. *(.)); --> <!--Configure Logger class--> <bean id="logger" class="com.mingqi.utils.Logger"></bean> <!--Use aop:config tag table name to start AOP configuration--> <aop:config> <aop:pointcut id="pt1" expression="execution(* com.mingqi.services.impl.*.*(..))"></aop:pointcut> <!--UseAop:aspectLabel indicates configuration facet--> <aop:aspect id="LogAdvice" ref="logger"> <!--Configure Pre-Notification: Execute before the entry point method executes <aop:before method="beforePrintLog" pointcut-ref="pt1"></aop:before>--> <!--Configuration Post Notification: Value after the entry point method has been properly executed.It and exception notifications can always execute only one <aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"></aop:after-returning>--> <!--Configure exception notifications: execute after the entry point method execution has generated an exception.It and post-notification can never execute more than one <aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"></aop:after-throwing>--> <!--Configure final notification: the entry point method will execute after it whether it executes properly or not <aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>--> <!--Configure surround notifications for detailed comments see the Logger class--> <aop:around method="aroundPringLog" pointcut-ref="pt1"></aop:around> </aop:aspect> </aop:config> </beans>
6. Create test classes
package com.mingqi.test; import com.mingqi.services.IAccountService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringIoc { @Test public void TestAccount() { ApplicationContext ac= new ClassPathXmlApplicationContext("beam.xml"); IAccountService accountService=(IAccountService) ac.getBean("accountSevice"); accountService.saveAccount(); accountService.updateAccount(22); accountService.deleteAccount(); } }