Detailed explanation of Spring AOP aspect programming application + AOP based on AspectJ

1, AOP overview

Spring AOP official

  • AOP: aspect oriented programming, relative to OOP object-oriented programming. The purpose of existence is to decouple. AOP enables a set of classes to share the same behavior. In OOP, interfaces can only be inherited and implemented, and class inheritance can only be single inheritance, which prevents more behaviors from being added to a group of classes. AOP makes up for the shortcomings of OOP.
  • The other is to make the business logic pay attention to the business itself rather than other things, such as transactions, for the sake of clear logic.
  • Spring's AOP is implemented through JDK's dynamic proxy and CGLIB.

2, Related terms

term describe
Notification / enhancement (Advice) The work that needs to be done is called notification. For example, transactions and logs are defined first, and then used where they are needed
Join point This is where notifications are allowed in spring
Pointcut Predicates matching connection points are actually filtered connection points. All methods in a class are connection points, but not all of them are required. Some connection points will be filtered as tangency points. If the notification defines the action or execution time of the aspect, the pointcut defines the execution place
Aspect In fact, it is the combination of notification and pointcut. Notification and pointcut jointly define all the contents of the aspect, what it does, when and where it is executed
Introduction Adding attributes and methods to an existing class without changing its code can make it have new behavior and state without modifying the existing class.
Target Notified objects
Weaving The process of adding facets to program code. Facets are woven into the target object at the specified connection point, and can be woven during the life cycle of the target object (compilation / loading / running)
1. Notification type
Notification type describe
Before (advance notice) Execute before method execution
After (post notification) Execute after method execution, whether normal or abnormal return
Afterreturning (notify after returning) Execute after method returns normally
Afterthrowing (exception notification) Execute when an exception is thrown
Around (surround notification) The method will be executed before and after execution, which is equivalent to before + after

Execution sequence: around > before > around > after > afterreturning

3, AOP annotation based on AspectJ

1. Tangent plane tangent point
annotation parameter
@Aspect value = ""
@PointCut value = "" ,argNames=""
2. Notification type
annotation parameter
@Before value = "" ,argNames=""
@After value = "" ,argNames=""
@Around value = "" ,argNames=""
@AfterReturning value = "" ,argNames="", pointcut="", returning = ""
@AfterThrowing value = "" ,argNames="", pointcut="", throwing=""
3. Expressions supported by @PointCut
expression describe Example
execution Connection point for matching method execution. Syntax: execution (method modifier (optional) return type classpath method name parameter exception mode (optional)) execution(public * (...) all public methods; Execution (set* (...)) any method starting with set); execution(* com.xyz.service.. (...)) matches all methods under the service package; execution(* com.xyz.service... (...)) indicates the method under the matching service package and its sub packages
within Restrict matching to connection points within certain types within(com.xyz.service.) Any connection point of the service package; within(com.xyz.service...) any connection point between the service package and its subpackages
this Specify the type of AOP proxy class this(com.xyz.service.AccountService) agent implements any connection point of the AccountService interface
target Specify the type of target object target(com.xyz.service.AccountService) the target object implements any connection point of the AccountService interface
args Specify the type of parameter args (java.io.Serializable) any connection point that takes a single parameter and passes a Serializable parameter at run time
bean Specify the type of parameter bean(tradeService) any connection point on a Spring bean named tradeService; Any connection point on a bean (Service) bean that has a name that matches the wildcard expression Service
@target Type with specified annotation @Target (org.springframework.transaction.annotation.Transactional) any connection point with @Transactional annotation on the target object
@args Specify annotated parameters passed at runtime @args (com.xyz.security.Classified) any connection point that takes a single parameter, and the runtime type of the passed parameter has a @Classified annotation
@within Match classes that use the specified annotation @within (org.springframework.transaction.annotation.Transactional) any connection point where the declaration type of the target object has a @Transactional annotation
@annotation Specifies the annotation applied by the method @Annotation (org.springframework.transaction.annotation.Transactional) executes any join point with @Transactional annotation on the method

4, AOP application scenarios

1. Logging
  • Section class
package com.spring.demo.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Description: Log facet class
 * @Version: 1.0
 */
@Slf4j
@Aspect
@Component
public class LogAspect {

	/**
	 * Determine the position of the pointcut, and determine which methods to enhance through some rules
	 */
	@Pointcut("within(com.spring.demo.controller.*Controller)") // Classes at the end of all controllers in the controller package
	public void controllerLogPointCut(){
	}

	/**
	 * Pre notification, specific enhanced code slice
	 *
	 * @Param joinPoint Connection point
	 */
	@Before("controllerLogPointCut()")
    public void controllerBeforeLog(JoinPoint joinPoint) {
		// How mvc gets requests
		RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();

		// Log requests
		log.info("Request type is {}", request.getMethod());
		log.info("Request url is {}", request.getRequestURL());
		log.info("Target is {}", joinPoint.getTarget().getClass());
	}

	/**
	 * Post notification, specific enhanced code slice
	 *
	 * @Param returnResult Return result of target class method
	 */
	@AfterReturning(pointcut = "controllerLogPointCut()", returning = "returnResult")
	public void controllerAfterLog(Object returnResult) {
		// How mvc gets the response
		RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
		HttpServletResponse response = ((ServletRequestAttributes) requestAttributes).getResponse();

		log.info("Response status is {}, data is {}", response.getStatus(), returnResult.toString());
	}

	/**
	 * Notification in case of exception, specific enhanced code slice
	 * 
	 * @Param exception Exception during execution of target class method
	 */
	// @AfterThrowing(pointcut = "controllerLogPointCut()", throwing = "exception") / / method 1
	@AfterThrowing(pointcut = "execution(* com.spring.demo.controller.*.*(..))", throwing = "exception") // Mode 2
	public void controllerAfterLog(Exception exception) {
		// How mvc gets the response
		RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();

		log.info("Request url is {}", request.getRequestURL());
		log.info("Inner exception is {}", exception.getMessage());
	}
}
  • test

During normal return, the Before and AfterReturning notifications take effect. The pre notification code is executed Before the method is executed, and the post return notification is executed after the method is called

When an exception returns, the Before and AfterThrowing notifications take effect. The pre notification code is executed Before the method is executed. When an exception occurs after an exception, the notification code is executed first, and then an exception fragment is thrown

2. Transaction management

Make up later...

Tags: Java Spring Spring Boot AOP Proxy

Posted by Locked on Mon, 30 May 2022 12:29:50 +0530