AOP Face Oriented Programming
Posted by khendar on Wed, 29 May 2019 18:27:59 +0200
1. Generation of Aspect Oriented Programming Requirements
- Code clutter: With more and more non-business requirements (logs, validation, etc.) added, the original business approach has expanded dramatically.Each approach must take into account multiple other concerns while handling core logic.
- Code Distribution: For example, log requirements, the same log code has to be repeated multiple times in multiple modules (methods) to meet this single requirement.If log requirements change, all modules must be modified.
2. Realizing Face-Oriented Programming
-
Classes that need to implement AOP are injected into the Spring container, for example:
1 package com.neuedu.aop;
2
3 import org.springframework.stereotype.Component;
4
5 @Component
6 public class RawCaculator implements MathCaculator{
7
8 @Override
9 public int add(int i, int j) {
10 int rs=i+j;
11 System.out.println(i+"+"+j+"="+rs);
12 return rs;
13 }
14
15 @Override
16 public int sub(int i, int j) {
17 int rs=i-j;
18 System.out.println(i+"-"+j+"="+rs);
19 return rs;
20 }
21
22 @Override
23 public int mul(int i, int j) {
24 int rs=i*j;
25 System.out.println(i+"*"+j+"="+rs);
26 return rs;
27 }
28
29 @Override
30 public int div(int i, int j) {
31 int rs=i/j;
32 System.out.println(i+"/"+j+"="+rs);
33 return rs;
34 }
35
36 }
Class of calculation methods to implement AOP
Implement Face Class
- Implement a facet class using pre-notification, post-notification, return notification, exception notification, and inject it into the Spring container
1 package com.neuedu.aop;
2
3 import static org.hamcrest.CoreMatchers.nullValue;
4
5 import java.util.Arrays;
6 import java.util.List;
7
8 import org.aspectj.lang.JoinPoint;
9 import org.aspectj.lang.ProceedingJoinPoint;
10 import org.aspectj.lang.Signature;
11 import org.aspectj.lang.annotation.After;
12 import org.aspectj.lang.annotation.AfterReturning;
13 import org.aspectj.lang.annotation.AfterThrowing;
14 import org.aspectj.lang.annotation.Around;
15 import org.aspectj.lang.annotation.Aspect;
16 import org.aspectj.lang.annotation.Before;
17 import org.springframework.core.annotation.Order;
18 import org.springframework.stereotype.Component;
19
20 @Component
21 //@Aspect Indicates that the current class is a tangent class
22 @Aspect
23 //@Order Represents the order in which the facets are executed. value The smaller the value, the higher the priority
24 @Order(value=50)
25 public class CaculatorAspect {
26 @Before(value = "execution(public int com.neuedu.aop.RawCaculator.*(int, int))")
27 public void showBeginLog(JoinPoint point){
28 //System.out.println("[Log [Pre-notification]");
29 //Get a list of parameters:
30 Object[] args = point.getArgs();
31 List<Object> asList = Arrays.asList(args);
32 //Get the method name:
33 Signature signature = point.getSignature();
34 String name = signature.getName();
35 System.out.println("[Log [Pre-notification] Target method name is:"+name+"The parameters are:"+asList);
36 }
37 @AfterThrowing(value = "execution(public int com.neuedu.aop.RawCaculator.*(..))" ,throwing="ex")
38 public void showThrowing(JoinPoint point,Exception ex){
39 //System.out.println("[Log [Exception Notification]");
40 System.out.println("[Log [Exception Notification] Exception information:"+ex);
41 }
42 @After(value = "execution(public int com.neuedu.aop.RawCaculator.*(..))")
43 public void showAfter(){
44 System.out.println("[Log [Post Notification]");
45 }
46 @AfterReturning(value = "execution(* * .*(..))",returning="result")
47 public void showAfterReturning(JoinPoint point,Object result){
48 //System.out.println("[Log [Return Notification]");
49 System.out.println("[Log [Return Notification] The return value of the target method is"+result);
50 }
51 }
Code labeled with a yellow background is declared notifications, including notification types and entry point expressions, which are described below with the entry point expression at the end
Before Pre-Notification: Notification to be executed before method execution
After Post Notification: Post Notification is performed after the connection point has completed, that is, when the connection point returns a result or throws an exception
Back to notification at @AfterReturning:
-
-
-
-
- Whether the connection point returns normally or throws an exception, the post-notification is executed.If you only want to log when the connection point returns, you should use a return notification instead of a post-notification.
-
Return value of access to connection point in return notification:
- In the return notification, the return value of the connection point can be accessed as long as the returning property is added to the @AfterReturning annotation.The value of this property is the name of the parameter used to pass in the return value
- A parameter with the same name must be added to the signature of the notification method.Spring AOP passes the return value through this parameter at run time
- The original tangent expression needs to appear in the pointcut property
@AfterThrowing exception notification: only perform exception notifications when an exception is thrown by a connection point.
-
-
-
-
Adding the throwing property to the @AfterThrowing annotation also provides access to exceptions thrown by the connection point.Throwable is the top-level parent of all error and exception classes, so any error and exception can be caught in the exception notification method.
-
- If you are interested in only one particular exception type, you can declare the parameter as the parameter type of another exception.Notifications are then executed only when exceptions to this type and its subclasses are thrown
2. Use wrapping notifications to implement facet classes and inject them into the Spring container
1 package com.neuedu.aop;
2
3 import java.util.Arrays;
4 import java.util.List;
5
6 import org.aspectj.lang.ProceedingJoinPoint;
7 import org.aspectj.lang.Signature;
8 import org.aspectj.lang.annotation.Around;
9 import org.aspectj.lang.annotation.Aspect;
10 import org.springframework.core.annotation.Order;
11 import org.springframework.stereotype.Component;
12
13 @Component
14 //@Aspect Indicates that the current class is a tangent class
15 @Aspect
16 @Order(value=40)
17 public class secondAspect {
18 @Around(value = "execution(* * .*(..))")
19 public Object Around(ProceedingJoinPoint point){
20 Object result=null;
21 Object[] args = point.getArgs();
22 List<Object> asList = Arrays.asList(args);
23 Signature signature = point.getSignature();
24 String name = signature.getName();
25 try{
26 System.out.println("[Transaction Log [Pre-notification] The target method is named:"+name+"The parameters are:"+asList);
27 try {
28 result=point.proceed(args);
29 } finally{
30 System.out.println("[Things Log [Post Notification]");
31 }
32 System.out.println("[Transaction Log [Return Notification] The return value of the target method is"+result);
33 }catch (Throwable e) {
34 System.out.println("[Event Log [Exception Notification] Exception information:"+e);
35 }
36 return result;
37 }
38 }
Around notifications:
-
-
-
-
- Surround notification is the most powerful of all notification types, providing full control over the connection point and even whether the connection point is executed.
-
For surround notifications, the parameter type of the connection point must be ProceedingJoinPoint.It is a subinterface of JoinPoint that allows you to control when and whether connection points are executed.
-
In surround notifications, you need to explicitly call ProceedingJoinPoint's proceed() method to execute the proxied method.If you forget to do this, the notification is executed, but the target method is not executed.
-
Note: The method that surrounds the notification needs to return the result of the target method execution, that is, call joinPoint.proceed(); the return value, otherwise a null pointer exception will occur.
3. Implement test classes
package junit.test;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.neuedu.aop.MathCaculator;
import com.neuedu.aop.RawCaculator;
public class TestCaculator {
@Test
public void test() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
//MathCaculator bean = ioc.getBean(RawCaculator.class); Not available (representing different types of classes)
//rawCaculator Even when using annotations id;again xml In the configuration file id
MathCaculator bean = (MathCaculator) ioc.getBean("rawCaculator");
bean.add(10, 5);
System.out.println();
bean.sub(14, 5);
System.out.println();
bean.mul(8, 7);
System.out.println();
bean.div(10, 0);
}
}
Test Class
3. About expression of entry point
1. Role:
Locate one or more specific connection points by expression.
2. Grammatical details:
1) Syntax format of entry point expression: execution([permission modifier] [return value type] [simple class name/full class name] [method name] ([parameter list]))
3. Reuse entry points: