Detailed AOP annotation development example in spring

  • 2020-06-07 04:31:59
  • OfStack

1. Introduction

AOP mainly contains the terms notification, pointcut, and join points, which are described as follows:

Notification (advice)

The notification defines what the aspect is and when to invoke it, and when does the invocation include the following

Before invokes the notification before the method is called After calls the notification after the method completes, whether or not the method executes successfully After-returning invokes the notification after the method executes successfully After-throwing invokes a notification after a method throws an exception Around notifications wrap notified methods and perform custom behavior before and after the notified method invocation

Point of contact (PointCut)

What and when does the notification define the aspect, where does the pointcut define, which matches the one or more join points that the notification will weave,
We usually specify these pointcuts using explicit class method names or using regular expressions to define matching class and method names.

The join (JoinPoint)

A join point is a point at which a facet can be inserted during the execution of an application. This point can be when a method is called, an exception is thrown, or even when a field is modified.
Slice code can use these join points to insert into the normal flow of the application and add new behaviors such as logging, security, transactions, caching, and so on.

joinPoint.getSignature().getDeclaringTypeName() You can get the class name (including the package name) of the calling method, joinPoint.getSignature().getName()    You can get the method name, Arrays.toString(joinPoint.getArgs())   What you get is a list of parameters for the method call, joinPoint.proceed()   You get the return result of the method

2. Annotation development

To declare a section, just add @ES37en attribute to the class name. For specific join points, we use @Pointcut, @Before, @After and so on.
We need to rely on the configuration of pom before declaring it


<dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjrt</artifactId>
 <version>1.6.11</version>
</dependency>
<dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjweaver</artifactId>
 <version>1.6.11</version>
</dependency>

example


package com.ganji.demo.service.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Service;
/**
 * Created by admin on 2015/9/2.
 */
@Aspect
@Service
public class XmlAopDemoUserLog {
//  Configuration point of tangency   And the parameters to pass  
 @Pointcut("execution(* com.ganji.demo.service.user.UserService.GetDemoUser(..)) && args(id)")
 public void pointCut(int id)
 {
 }
//  Configure connection points   Notification when the method starts to execute 
 @Before("pointCut(id)")
 public void beforeLog(int id) {
  System.out.println(" Start performing the advance notification   logging :"+id);
 }
//  Method is notified after execution 
 @After("pointCut(id)")
 public void afterLog(int id) {
  System.out.println(" Start executing the postnotification   logging :"+id);
 }
//  Notification after successful execution 
 @AfterReturning("pointCut(id)")
 public void afterReturningLog(int id) {
  System.out.println(" Method is notified after successful execution   logging :"+id);
 }
//  Notification after an exception is thrown 
 @AfterThrowing("pointCut(id)")
 public void afterThrowingLog(int id) {
  System.out.println(" Method throws an exception and executes the notification   logging "+id);
 }
//  Surrounding the notification 
 @Around("pointCut(id)")
 public Object aroundLog(ProceedingJoinPoint joinpoint,int id) {
  Object result = null;
  try {
   System.out.println(" Start of surround notification   logging "+id);
   long start = System.currentTimeMillis();
   // There are return parameters   Returns a value 
   result = joinpoint.proceed();
   long end = System.currentTimeMillis();
   System.out.println(" Total execution time " + (end - start) + "  ms ");
   System.out.println(" End of loop notification   logging ");
  } catch (Throwable t) {
   System.out.println(" There is an error ");
  }
  return result;
 }
}

Synchronization issues in AOP sections

In WebLogAspect section, two independent functions, doBefore and doAfterReturning, are respectively used to realize the content executed after the pointcut header and pointcut return.
If we want to count the processing time of the request, we need to record the time at doBefore and calculate it at doAfterReturning by the current time and the time recorded at the beginning
Gets the elapsed time of the request processing.

Can we define a member variable in the WebLogAspect section to give access to doBefore and doAfterReturning1? Will there be synchronization issues?

Sure, there are synchronization issues with defining base types directly here, so we can introduce ThreadLocal objects and record them as follows:


@Aspect
@Component
public class WebLogAspect {
 private Logger logger = Logger.getLogger(getClass());
 ThreadLocal<Long> startTime = new ThreadLocal<>();
 @Pointcut("execution(public * com.juzi.web..*.*(..))")
 public void webLog(){}
 @Before("webLog()")
 public void doBefore(JoinPoint joinPoint) throws Throwable {
  startTime.set(System.currentTimeMillis());
  //  Omit logging content 
 }
 @AfterReturning(returning = "ret", pointcut = "webLog()")
 public void doAfterReturning(Object ret) throws Throwable {
  //  The request is processed and the content is returned 
  logger.info("RESPONSE : " + ret);
  logger.info("SPEND TIME : " + (System.currentTimeMillis() - startTime.get()));
 }
}

Priority of AOP sections

Due to the implementation of Web, the program is well decoupled, but it also brings a number of problems. For example, we may do multiple facets to the Web layer to verify the users.
Check head information and so on, this time often encounter section processing order problem.

So, we need to define the priority of each aspect, and we need the @Order (i) annotation to identify the priority of the aspect. The smaller the value of i, the higher the priority.
Suppose we have one more section CheckNameAspect to verify that name must be didi and we set @Order (10),
While WebLogAspect above is set as @Order (5), so WebLogAspect has a higher priority. At this time, the execution order is as follows:

The @Order (5) content is executed first in @Before and then the @Order (10) content

The @ES102en (10) content is executed first in @After and @ES101en, followed by the @ES103en (5) content

So we can summarize it this way:

The operation before the pointcut is performed from the smallest to the largest value of order Operations after pointcuts are performed from large to small according to the value of order

conclusion

The above is the whole content of this article, I hope the content of this article can bring 1 definite help to your study or work, if you have any questions, you can leave a message to communicate.


Related articles: