What is the AOP

To understand AOP(Aspect Oriented Programming), it is often compared with another term, OOP(Object Oriented Programming).

In OOP mode, when multiple objects with no inheritance need to reference the same common behavior, a lot of redundant code can be generated. Best understood as our logging module or security monitoring etc. To log a call to a function, we need to introduce a logging object to the call, but this logging object is not required for the business class.

The focus of AOP is horizontal and a useful complement to OOP. In order to make the business class more focused on the specific property development, while the addition of other module functions is not modified to the objective function, functional decoupling can be achieved by configuring sections.

AOP terminology

  • Join point: This corresponds to the specific object being intercepted, and since Spring only supports methods, an intercepted object is often a specific method.
  • Point cut: Sometimes our aspect applies not only to a single method, but also to different methods of multiple classes, which can be defined by regular expressions and designator rules.
  • Advice:
    1. Before advice
    2. After Advice
    3. Around Advice
    4. AfterReturning Advice
    5. Exception Advice
  • Target: indicates the proxy object.
  • Introduction: Introducing new classes and methods that enhance the functionality of an existing Bean.
  • Weaving: Weaving is a process that uses dynamic proxy technology to generate dynamic objects for the original service object, intercepts join points that match the pointcut definition, and weaves various kinds of notifications into the agreed process.
  • An aspect: a piece of content that defines pointcuts, notifications, and introductions.

Now that we know the general concept, let’s go ahead and see how to actually implement a section.

AOP use

The business class code is TestController.

@RestController
@RequestMapping("/test")
public class TestController {

    public void testFunc(String userName) {
        //do something
        System.out.println("Hello "+ userName); }}Copy the code

Define simple sections

@Aspect
@Component
public class MyAspect {

  @Pointcut("execution(public * com.test.TestController.testFunc(..) )")
  public void pointCut() {}

  @Before("pointCut()")
  public void before() {
      log.info("MyAspect before ...");
  }

  @After("pointCut()")
  public void after() {
      log.info("MyAspect after ...");
  }

  @AfterReturning("pointCut()")
  public void afterReturning() {
      log.info("MyAspect after returning ...");
  }

  @AfterThrowing("pointCut()")
  public void afterThrowing() {
      log.info("MyAspect after throwing ...");
  }

  @Around("pointCut()")
  public void around(ProceedingJoinPoint joinPoint) throws Throwable {
      log.info("MyAspect around before ...");
      joinPoint.proceed();
      log.info("MyAspect around after ..."); }}Copy the code

The example above is a simple aspect definition implementation of the business method testFunc. At this point, one of the most basic aspect classes has been implemented. Let’s move on to learn more about AOP.

Aspect notes Point notes

  • Use the @Aspect annotation to define a Java class as an Aspect class, such as MyAspect in the example.
  • Use @pointCut to define a Pointcut, which can be a regular expression, an annotation, etc.
  • Cut into content at different points in the pointcut as needed
    • Use @before to cut in at the beginning of the pointcut
    • Use @After to cut into the content at the end of the pointcut
    • Use @AfterRETURNING to cut into the content after the pointcut returns (this can be used to do some processing on the returned value)
    • Use @around to cut in before and after the pointcut and control when the pointcut’s own content is executed
    • Use @Afterthrowing to handle the logic after an exception is thrown inside the content section

Define the section of the processing parameter

Spring AOP use org. Aspectj. Lang. JoinPoint type obtain join point data, the first parameter can be any notification method is JoinPoint (around notification is ProceedingJoinPoint, JoinPoint subclass).

  1. JoinPoint: Provides data such as the target object, proxy object, and method parameters of the notified method
  2. ProceedingJoinPoint: Used only to surround the advice, using the proceed() method to execute the target method

If the parameter type is JoinPoint or ProceedingJoinPoint, you can omit the parameter name from the argNames attribute (optional). Objects of the type will be automatically passed in, but they must be the first parameter.

@Aspect
@Component
public class MyAspect {

  @Pointcut("execution(public * com.test.TestController.testFunc(..) )")
  public void pointCut() {}

  @Before("pointCut()")
  public void before(JoinPoint joinPoint) {
      String method = joinPoint.getSignature().getName();
      log.info("MyAspect before Method :{} ::{}", joinPoint.getSignature().getDeclaringTypeName(), method);
      ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
      HttpServletRequest request = attributes.getRequest();
      log.info("ClientIP: {}", request.getRemoteAddr());
  }

  @After("pointCut()")
  public void after(JoinPoint joinPoint) {
      String method = joinPoint.getSignature().getName();
      log.info("MyAspect after Method :{} ::{}", joinPoint.getSignature().getDeclaringTypeName(), method);
  }

  @AfterReturning("pointCut()")
  public void afterReturning(JoinPoint joinPoint) {
      String method = joinPoint.getSignature().getName();
      log.info("MyAspect after Returning Method :{} ::{}", joinPoint.getSignature().getDeclaringTypeName(), method);
  }

  @AfterThrowing("pointCut()")
  public void afterThrowing(JoinPoint joinPoint) {
      log.info("MyAspect after throwing ...");
  }

  @Around("pointCut()")
  public void around(ProceedingJoinPoint joinPoint) throws Throwable {
      log.info("MyAspect around before ...");
      joinPoint.proceed();
      log.info("MyAspect around after ..."); }}Copy the code

Define sections that have an execution priority

  1. The execution priority is configured by annotating @order. The smaller the Order number, the higher the execution priority.
@aspect @Component @order (-1) public class MyAspect2 {//Copy the code
  1. By implementing org. Springframework. Core. Ordered interface
@Component
@Aspect
public class MyAspect2 implements Ordered { 
    @Override
    public int getOrder() {
        //do something to gen order.
        return2; }}Copy the code

AOP cut into detail

The definition of a PointCut consists of two parts: the PointCut expression and the PointCut signature.

//Pointcut representation @pointcut ("execution(public * com.test.TestController.testFunc(..) )") //Pointcut signing public voidpointCut() {}
Copy the code

The execution expression format:

execution(
modifier-pattern?
ret-type-pattern
declaring-type-pattern?
name-pattern(param-pattern)
throws-pattern?)
Copy the code

Each pattern in the parentheses is represented respectively

  1. Modifier matching (modifier-pattern?)
  2. Return value matching (ret-type-pattern)
  3. Classpath matching (variable -type-pattern?)
  4. Method name matching (name-pattern)
  5. Parameter matching ((param-pattern))
  6. Exception type matching (throws-pattern?) “, followed by “?” Is optional.

Now let’s look at a few examples.

  1. execution(* *(..) ): matches all methods
  2. execution(public * com.test.TestController.*(..) ): matches all public methods in the com.test.TestController class
  3. execution(* com.test.. *. * (..) ): matches all methods in the com.test package

First introduced here, welcome to leave a message to discuss sharing ~