Catalog
1. Steps to notify annotations using AOP
1.1 pom. Add maven dependencies to XML files
1.2 Declare the automatic proxy generator for AspectJ in the Spring configuration file
2.2 @AfterReturning: Post Notification
2.3 @Around: surround notifications
2.4 @AfterThrowing: exception notification
2.5 @After: Final Notification
3. @Pointcut Defines a Start Point
1. Steps to notify annotations using AOP
Use the annotations of the apsectj framework to implement the pre-notification as follows:
1. New Maven Project
2. Modify the pom.xml, add dependencies
- spring-context dependency, spring-aspects dependency, junit
3. Create business interfaces and implementation classes
4. Create a facet class (generic class)
1) Add @Aspect above the class
2) Define a method in the class that represents the function of the tangent. Add notification annotations in the AspectJ framework above the method
For example: @Before(value="entry point expression")
5. Create a spring profile
1) Declare the target object
2) Declare facet class objects
3) Declare automatic proxy generator
6. Create test classes to test the functionality of facets when the target method is executed
1.1 pom. Add maven dependencies to XML files
1. spring dependency
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.5.RELEASE</version> </dependency>
2. spring-aspects dependency
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.2.5.RELEASE</version> </dependency>
3. Unit test dependencies (may or may not be primarily for testing)
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency>
1.2 Declare the automatic proxy generator for AspectJ in the Spring 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 https://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- Declare the automatic proxy generator:The purpose is to create a proxy for the target object (that is, to have two proxies) bean Combine) call aspectj Functions in Framework, Find spring All target objects in the container. Functions to add each target object to a facet class ,Generate a proxy that modifies the target object in memory, which is the proxy object--> <aop:aspectj-autoproxy /> </beans>
2.5 Notification Notes in AOP
2.1 @Before: Pre-notification
/* Definition of pre-notification method 1.The method is public 2. The method is void 3. Method Name Customization 4.Method can have parameters, if joinpoint or not */ /** * @Aspect: Notes for the tangent class. Location: Place on top of a class. Role:: Indicates that the current class is a tangent class * * @Before:Before advice * Attribute: value entry point expression that indicates where a tangent will be executed In this method, the function of the tangent will be executed simultaneously. * Location: Method above * Features: 1. Execution time: Executed before the target method, * 2.Will not affect the execution of the target method * 3.The execution result of the target method will not be modified. * Notification methods in the facet class can have parameters * joinPoint Must be it. Represents a business method being executed. Equivalent to Method in Reflection * Requirements for use: Must be the first parameter list. * Role: Get information about method execution, such as method name, method parameter set */
Interface classes for service packages:
package com.liuhaiyang.service; public interface SomeService { void doSome(String name,Integer age); void doOther(); }
Impl Package Implementation Class in Peer Directory
package com.liuhaiyang.service.Impl; import com.liuhaiyang.service.SomeService; public class SomeServiceImpl implements SomeService { @Override public void doSome(String name, Integer age) { System.out.println("Business methods dosome(),"+name+"Create merchandise orders,"+age); } @Override public void doOther() { System.out.println("doOther Method Executed============"); System.out.println("\r\n"); } }
Perfect function through pre-notification
package com.liuhaiyang.handle; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import java.util.Date; /** *@Aspect: Notes for the tangent class. Location: Place on top of a class. Role:: Indicates that the current class is a tangent class */ @Aspect //The comment indicates that this class is a tangent class public class MyAspect { /* Definition of pre-notification method 1.The method is public 2. The method is void 3. Method Name Customization 4.Method can have parameters, if joinpoint or not */ /** * @Before:Before advice * Attribute: value entry point expression that indicates where a tangent will be executed In this method, the function of the tangent will be executed simultaneously. * Location: Method above * Features: 1. Execution time: Executed before the target method, * 2.Will not affect the execution of the target method * 3.The execution result of the target method will not be modified. */ // @Before(value ="execution(public void com.liuhaiyang.service.Impl.SomeServiceImpl.doSome(String ,Integer))") // @Before (value = "execution (* *..SomeServiceImpl.doSome(.))")// Slicing can be added to any parameter of the dosome method @Before(value ="execution(* *..SomeServiceImpl.do*(..))") //Any parameter of all methods starting with do can add slicing /* You can write a @Before but you need to write a new method. And the order of the two Befores cannot be determined. */ /** *Notification methods in the facet class can have parameters * joinPoint Must be it. Represents a business method being executed. Equivalent to Method in Reflection * Requirements for use: Must be the first parameter list. * Role: Get information about method execution, such as method name, method parameter set */ public void myBefore(JoinPoint jp){ //Get the definition of the method System.out.println("In the preceding notification, get the definition of the target method:" +jp.getSignature()); //The result is: in the pre-notification, get the definition of the target method: void com.liuhaiyang.service.SomeService.doOther() System.out.println("In the preceding notification, get the method name="+jp.getSignature().getName()); //Get method execution parameters Object[] obj=jp.getArgs(); int[] a={}; for(Object ob:obj) {System.out.println("The parameters are:"+ob);} String getname=jp.getSignature().getName(); if("doSome".equals(getname)){ //Cutting Code System.out.println(getname+"Pre-notification, facet function, execute before target method:"+new Date()); } else if("doOther".equals(getname)){ System.out.println(getname+"Pre-notification, facet function, execute before target method:"+new Date()); } } }
In the configuration file application. Declarations to add objects and agents to XML files
<?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 https://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- Declare the target object--> <bean id="someservice" class="com.liuhaiyang.service.Impl.SomeServiceImpl"/> <!-- Declare Face Class Objects--> <bean id="myaspect" class="com.liuhaiyang.handle.MyAspect"/> <!-- Declare the automatic proxy generator:The purpose is to create a proxy for the target object (that is, to have two proxies) bean Combine) call aspectj Functions in Framework, Find spring All target objects in the container. Functions to add each target object to a facet class ,Generate a proxy that modifies the target object in memory, which is the proxy object--> <aop:aspectj-autoproxy /> </beans>
Test Class
@Test public void test01(){ String conf="application.xml"; ApplicationContext ctx= new ClassPathXmlApplicationContext(conf); //Processing of Join Agent //1. When the target method is executed, it has tangent function. // 2. The service object is the changed proxy object com.sun.proxy.$Proxy10 SomeService someservice=(SomeService) ctx.getBean("someservice"); System.out.println(someservice.getClass().getName()); //Someservice here is a proxy object, not SomeService someservice.doSome("Zhang San",22); }
Result:
See if doOther works and what the results are
Test Class
@Test public void test02(){ String conf="application.xml"; ApplicationContext ctx=new ClassPathXmlApplicationContext(conf); SomeService someservice=(SomeService) ctx.getBean("someservice"); someservice.doOther(); someservice.doSome("Weekly",25); }
Result Screenshot:
2.2 @AfterReturning: Post Notification
/* Definition of post-notification method 1.The method is public 2. The method is void 3. Method Name Customization 4.Method has parameters, Object type is recommended */ /** @AfterReturning: after returning advise * Attribute: value entry point expression * returning Custom variable representing the return value of the target method * The custom variable name must be the same as the parameter name of the notification method. * Location: On top of the method * Features: 1. After the target method, execute. * 2.The result of execution of the target method can be obtained. * 3.Will not affect the execution of the target method *Parameters of the method: * Object res: Represents the return value of the target method, and uses res to accept the result of a call to doOther. * Object res = doOther(); * * Execution order of post-notifications * Object res=someserviceImpl.doOther(..); * myAfterReturning(res); */
service interface
package com.liuhaiyang.service; import com.liuhaiyang.Stduent; public interface SomeService { void doSome(String name,Integer age); Stduent doOther(String name, Integer age); }
Implementation class:
package com.liuhaiyang.service.Impl; import com.liuhaiyang.Stduent; import com.liuhaiyang.service.SomeService; public class SomeServiceImpl implements SomeService { @Override public void doSome(String name, Integer age) { System.out.println("\r\n"); System.out.println("Business methods dosome(),"+name+"Create merchandise orders,"+age); } @Override public Stduent doOther(String name, Integer age) { Stduent student=new Stduent(); System.out.println("Execute business methods doOther,"+name+"Handling Inventory"+age); student.setName(name); student.setAge(age); return student; } }
Perfect function
package com.liuhaiyang.handle; import com.liuhaiyang.Stduent; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; @Aspect //The comment indicates that this class is a tangent class public class MyAspect { @AfterReturning(value = "execution(* *..SomeServiceImpl.doOther(..))", returning="res") public void myAfterReturning(JoinPoint jp ,Object res){ // JoinPoint must precede Object System.out.println(res.getClass().getName()); if(res!=null){ ((Stduent) res).setName("liuhaiyang"); ((Stduent) res).setAge(23); } System.out.println("Postnotification to get the results returned+"+res); } }
Configuration file (code and above configuration file are hardly written, write point core):
<!-- Declare the target object--> <bean id="someservice" class="com.liuhaiyang.service.Impl.SomeServiceImpl"/> <!-- Declare Face Class Objects--> <bean id="myaspect" class="com.liuhaiyang.handle.MyAspect"/> <!-- Declare the automatic proxy generator:The purpose is to create a proxy for the target object (that is, to have two proxies) bean Combine) call aspectj Functions in Framework, Find spring All target objects in the container. Functions to add each target object to a facet class ,Generate a proxy that modifies the target object in memory, which is the proxy object--> <aop:aspectj-autoproxy />
Test class:
@Test public void test01(){ String conf="application.xml"; ApplicationContext ctx=new ClassPathXmlApplicationContext(conf); SomeService someservice=(SomeService) ctx.getBean("someservice"); Stduent res=someservice.doOther("Vada",30); System.out.println(res); someservice.doSome("Weekly",25); }
Result Screenshot:
2.3 @Around: surround notifications
/* Definition of surround notification method 1.The method is public 2. Method must have a return value, Object type 3 is recommended. Method Name Customization 4.Method must have ProceedingJoinPoint parameter; */ /** * @Around: Around Advice * Attribute: value entry point expression * Location: above the method definition * Return value: Object, which means the target method is called in order to get the execution result (not necessarily the return value of the target method itself) * Parameter: ProceedingJoinPoint, equivalent to Method in Reflection. * Role: Executes the target method, equal to Maethod.invoke() * ProceedingJoinPoint Inherited JoinPoint. * Features: 1. Enhance functionality before and after the target method * 2.Controls whether the target method is executed. * 3.Modify the execution result of the target method. */
service interface:
package com.liuhaiyang.service; public interface SomeService { void doSome(String name,Integer age); String doOther(String name, Integer age); String doFirst(String name); }
Implementation class:
package com.liuhaiyang.service.Impl; import com.liuhaiyang.service.SomeService; public class SomeServiceImpl implements SomeService { @Override public void doSome(String name, Integer age) { System.out.println("\r\n"); System.out.println("Business methods dosome(),"+name+"Create merchandise orders,"+age); } @Override public String doOther(String name, Integer age) { System.out.println("Execute business methods doOther,"+name+"Handling Inventory"+age); return "student"; } @Override public String doFirst(String name) { System.out.println(name+"Business method executed doFirst,Handle Inventory"); return "abcd"; } }
Enhance functionality through surround notifications:
package com.liuhaiyang.handle; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import java.util.Date; @Aspect //The comment indicates that this class is a tangent class public class MyAspect { @Around("execution(* *..SomeServiceImpl.doFirst(..))") public Object myArroud(ProceedingJoinPoint pjp) throws Throwable { //Get the parameter value when the method executes String name=""; Object args[]= pjp.getArgs(); if (args!=null & args.length>0){ Object arg=args[0]; if (arg!=null){ name=(String) arg; } } for (Object arg:args){ //View all parameters of doFirst System.out.println(arg); } System.out.println("Performed surround notification myAroud Method that outputs log time before the target's method"+new Date()); Object str=null; if("Little Red".equals(name)){ //Execute target method (doFirst) str=pjp.proceed();//pjp.proceed() is equivalent to Maethod.invoke() denotes the execution of a method in doFirst } System.out.println("After wrapping notifications, add transaction commits after your target method"); return str; //Anything to go back here is anything. If str is the return parameter of doFirst, if abc is the return parameter of abc } }
Profile:
<!-- Declare the target object--> <bean id="someservice" class="com.liuhaiyang.service.Impl.SomeServiceImpl"/> <!-- Declare Face Class Objects--> <bean id="myaspect" class="com.liuhaiyang.handle.MyAspect"/> <!-- Declare the automatic proxy generator:--> <aop:aspectj-autoproxy />
Test class:
package com.liuhaiyang; import com.liuhaiyang.service.Impl.SomeServiceImpl; import com.liuhaiyang.service.SomeService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class test01 { @Test public void test02(){ String conf="application.xml"; ApplicationContext ctx=new ClassPathXmlApplicationContext(conf); SomeService someservice=(SomeService) ctx.getBean("someservice"); // String res=someservice.doOther("Vada", 30); // System.out.println(res); // someservice.doSome("refreshing", 25); String name=someservice.doFirst("Little Red"); System.out.println(name); } }
Result Screenshot:
2.4 @AfterThrowing: exception notification
/* Definition of exception notification method 1.The method is public 2. Method does not return a value, it is void 3. Method Name Customization 4.Method has an argument of Exception; */ /** * @AfterThrowing:Exception Notification * Attribute: value: entry point expression * throwing A custom variable that represents an exception thrown by the target method. The variable name must be the same as the parameter name of the notification method * Location: On top of the method * Features: 1. Executed after the target method throws an exception, no exception does not execute * 2.Can get exception information for target method * 3.Not an exception handler. You can be notified that an exception has occurred, you can send an email, and you can notify the developer by text message. * Can be viewed as a monitor for the target method. * Amount to: * try{ * execution(* *..SomeServiceImpl.doSecond(..))" * } catch(Exception ex){ * System.out.println("Exception notification, executed when the target method throws an exception, exception reason: "+ex.getMessage()"; * } */
service interface:
package com.liuhaiyang.service; public interface SomeService { void doSecond(String name); }
Implementation class:
package com.liuhaiyang.service.Impl; import com.liuhaiyang.service.SomeService; public class SomeServiceImpl implements SomeService { @Override public void doSecond(String name) { int a=10/0; System.out.println(name+"Business method executed doSecond"); } }
Exceptional enhancements:
package com.liuhaiyang.handle; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import java.util.Date; @Aspect //The comment indicates that this class is a tangent class public class MyAspect { @AfterThrowing(value = "execution(* *..SomeServiceImpl.doSecond(..))",throwing = "ex") public void myAfterThrowing(Exception ex){ System.out.println("Exception notification, executed when the target method throws an exception, the cause of the exception:"+ex.getMessage()); /* Something you can do about an exception: record the time, location, and so on. Send mail and SMS to developers */ } }
The configuration file is the same as above. There's nothing to write about, and it's been written several times
Test class:
@Test public void test02(){ String conf="application.xml"; ApplicationContext ctx=new ClassPathXmlApplicationContext(conf); SomeService someservice=(SomeService) ctx.getBean("someservice"); someservice.doSecond("Path"); }
Result Screenshot:
2.5 @After: Final Notification
/** * @After:Final Notification * Attribute: value entry point expression * Location: On top of the method * Features: 1. Executed after the target method. * 2.Always executed. * 3.It can be used as the final end of the program. For example, clear temporary data, variables, clear memory * Amount to: * try(){ * SomeServiceImpl.doThird(..) * }finally(){ * myAfter(); * } */
service interface:
package com.liuhaiyang.service; public interface SomeService { void doThird(String naem); }
Implementation class:
package com.liuhaiyang.service.Impl; import com.liuhaiyang.service.SomeService; public class SomeServiceImpl implements SomeService { @Override public void doThird(String name) { System.out.println(name+"Business method executed doThird"); } }
Final notification enhancements:
package com.liuhaiyang.handle; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import java.util.Date; @Aspect //The comment indicates that this class is a tangent class public class MyAspect { @After("execution(* *..SomeServiceImpl.doThird(..))") public void myAfter(){ System.out.println("Final notification, this code will always be executed!!"); //Even if an exception occurs, the code will be executed } }
The configuration file is the same as above.
Test class:
@Test public void test03(){ String conf="application.xml"; ApplicationContext ctx=new ClassPathXmlApplicationContext(conf); SomeService someservice=(SomeService) ctx.getBean("someservice"); someservice.doThird("Pear Blossom"); }
Result Screenshot:
3. @Pointcut Defines a Start Point
When more notification enhancement methods use the same execution entry point expression, it is more cumbersome to write and maintain. AspectJ provides the @Pointcut annotation to define an execution entry point expression.
The usage is to annotate @Pointcut on a method and use that method name as a starting point for all execution value attributes in the future. This represents the entry point for the @Pointcut definition. This method of using the @Pointcut annotation typically uses the private ly identified method, which is a method that has no real effect.
Enhanced code is much the same as the above code. Not written:
package com.liuhaiyang.handle; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import java.util.Date; @Aspect //The comment indicates that this class is a tangent class public class MyAspect { //Before advice @Before("mypt()") public void myBefer(){ System.out.println("Pre-notification, executed before target method"); } //Final Notification @After("mypt()") public void myArroud() { System.out.println("Final notification, at the end of the method, whether an exception occurs or not"); } /** * @Pointcut:Define and manage entry points, not notification notes. Can write multiple * Attribute: value entry point expression (can be omitted) * Location: Above a custom method, this method can be thought of as an alias for the entry point expression. * In other notification notes, you can use the method name to indicate that you are using this entry point expression */ @Pointcut("execution(* *..SomeServiceImpl.doThird(..))") public void mypt(){ //No code required } }