Springboot integrates Aspectj and Aspectj basic syntax

We know that AOP (aspect oriented programming) brings great convenience to developers, especially the apes with obsessive-compulsive disorder. There are a pile of redundant code irrelevant to the actual business in the project. You want to tear it up once you see it.

It's convenient for you to sort out the relevant articles online. I can't find them all.

The following example source code portal

https://gitee.com/peterven/aoptest

Out of the box

Core dependency

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

Scenario 1 (before interface method execution)

package com.gitee.peterven.controller.admin;

@Slf4j
@RestController
public class AdminController {

    @GetMapping("admin/hello")
    public void hello() {
        log.info("I am admin method!");
    }
}
@Slf4j
@Aspect
@Component
public class MyAspect {

    @Before("execution(public * com.gitee.peterven.controller.admin.*.*(..))")
    public void beforeTest() throws Throwable {
        log.info("before invoke");
    }
}

Execution log

before invoke
I am admin method!

Grammar analysis

@Before        // Indicates that the method is woven in before it is executed
execution 	   // Represents the method executed according to the matching rule
public 		   // The method representing the match must be public
* 			   // The return value of the matching method can be of any type
com.gitee.peterven.controller.admin.*  // The matching method is in any class under the package
*(..)          // Indicates that the matching method name is arbitrary and the input parameter has no requirements

be careful

@Before is the annotation of the method before execution, so the pointcut object ProceedingJoinPoint can not be passed into the pointcut method, otherwise it will throw an exception.

@Slf4j
@Aspect
@Component
public class MyAspect {

    @Before("execution(public * com.gitee.peterven.controller.admin.*.*(..))")
    public void beforeTest(ProceedingJoinPoint joinPoint) throws Throwable {
        joinPoint.proceed();
        log.info("before invoke");
    }
}
Error creating bean with name 'tomcatServletWebServerFactory' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryConfiguration$EmbeddedTomcat.class]: BeanPostProcessor before instantiation of bean failed; nested exception is java.lang.IllegalArgumentException: 
ProceedingJoinPoint is only supported for around advice

Scenario 2 (before and after implementation of interface method)

package com.gitee.peterven.controller;

@Slf4j
@RestController
public class BaseController {

    @GetMapping("base/hello")
    public User hello (Integer i) {
        try {
            log.info("basecontroller method start");
        } catch (Exception e) {
            log.info("basecontroller method exception");
            throw e;
        } finally {
            log.info("basecontroller method finally");
        }
        return new User("gitee", 20);
    }
}
 // Any method under controller package
    @Around("execution(public * com.gitee.peterven.controller.*.*(..))")
    public Object systemTimer(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        log.info("Method to perform pre work");
        Object result = joinPoint.proceed();
        log.info("Methods are executed in total{}millisecond", System.currentTimeMillis() - start);
        log.info("Method performs post-processing");
        return result; // Remember to return the result
    }

Execution log

Method to perform pre work
basecontroller method start
basecontroller method finally
 The method executed for a total of 9 milliseconds
 Method performs post-processing

Grammar analysis

@Around        // Indicates that the method is woven before and after execution
execution 	   // Represents the method executed according to the matching rule
public 		   // The method representing the match must be public
* 			   // The return value of the method representing the match can be of any type
com.gitee.peterven.controller.*  // The matching method is in any class under the package
*(..)          // Indicates that the matching method name is arbitrary and the input parameter has no requirements

The following theoretical knowledge is used as a supplement, and those you don't want to see can be omitted

What is AOP

Compared with OOP, AOP deals with some business irrelevant problems, such as logging, global exception handling, transaction management, etc. These crosscutting problems will not affect the implementation of the main logic, but will be scattered to all parts of the code and difficult to maintain. AOP is to separate these problems from business logic and achieve the purpose of decoupling from the main business logic.

Professional terms

  • joint point
    • Connection point, in daily use, can be understood as an object method.
  • pointcut
    • Tangent point, the predicate expression used to match the join point.
  • Advice
    • Notification refers to what a section needs to do at a specific connection point.
  • Aspect
    • Facet, which is a collection of multiple tangent points.
  • weaving
    • Weaving, the process of applying the aspect to the target object. This process can be completed at compile time (for example, using AspectJ compiler), class load time and run time. Spring AOP is completed at runtime.
  • Advisor
    • This concept is proposed from the AOP support of Spring 1.2. An Advisor is equivalent to a small aspect. The difference is that it only has one advice, which is often encountered in transaction management.
  • Target Object
    • Target object, the object notified by one or more aspects.
  • AOP proxy
    • AOP agent.

What is Aspectj

A framework of aop is implemented

Aspectj official website (I feel lonely watching it on the official website)
http://www.eclipse.org/aspectj/

AspectJ is	 a seamless aspect-oriented extension to the Javatm programming languageJava platform compatibleeasy to learn and use 	AspectJ enablesclean modularization of crosscutting concerns, such as error checking and handling, synchronization, context-sensitive behavior, performance optimizations, monitoring and logging, debugging support, and multi-object protocols

Class annotation @ Aspect

The annotation of aspect declaration usually creates a class to manage aop, and the annotation is added to the class, indicating that aop will be implemented in Aspectj mode.

package org.aspectj.lang.annotation;

/**
 * Aspect declaration 
 *
 * @author Alexandre Vasseur
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Aspect {

    /**
     * @return the per clause expression, defaults to singleton aspect.
     * Valid values are "" (singleton), "perthis(...)", etc
     */
    public String value() default "";
}

Common method annotation

  • @Before
    • Before method execution
  • @After
    • Execute after method
  • @AfterReturning
    • Method before returning a value
  • @AfterThrowing
    • Execute after throwing an exception
  • @Around
    • Method before and after execution

Throw abnormal conditions

package com.gitee.peterven.controller.admin;

@Slf4j
@RestController
public class AdminController {

    @GetMapping("admin/hello")
    public String hello() {
        try {
            log.info("controller method start");
            int i = 1 / 0;
        } catch (Exception e) {
            log.info("controller method exception");
            throw e;
        } finally {
            log.info("controller method finally");
        }
        return "haha";
    }
}

results of enforcement

@Around before invoke
@Before....
controller method start
controller method exception
controller method finally
@AfterThrowing....
@After....

If no exception is thrown, the result is as follows

@Around before invoke
@Before....
controller method start
controller method finally
@AfterReturnning...
@After....
result is:finish
@Around after invoke

Tangent expression syntax

@Pointcut("xxxx")

Tangent function

categoryfunctionexplainremarks
Method tangent functionexecution( )Represents all target class method connection points that meet a matching pattern.
Method tangent function@annotation( )Represents the connection point of the target class method annotated with a specific annotation.
Method input parameter tangent point functionargs( )Specify the connection point by identifying the type definition of the input parameter object when the target class method runs.The experiment failed. I'll study it again when I have time
Method input parameter tangent point function@args( )The connection point is specified by judging whether the class of the input parameter object of the target class method is marked with a specific annotation.The experiment failed. I'll study it again when I have time
Objective tangent functionwithin( )Represents all connection points under a specific domain.
Objective tangent function@within( )If the target class matches a Class A by type, and class A is marked with a specific annotation, all connection points of the target class match the tangent point.
Objective tangent functiontarget( )Represents all connection points under a specific domain. Can contain its subclasses or implementation classes.
Objective tangent function@target( )If the target class is annotated, all connection points of the target class match the tangent point.The experiment failed. I'll study it again when I have time
Proxy tangent functionthis( )If the proxy class matches the specified class by type, all connection points of the proxy target class match the tangent point.

execution

Match the corresponding method according to the expression

usage

  • @Pointcut("execution(public * com.gitee.peterven.controller.admin.AdminController.*(..))")
    • Any method under AdminController class
  • @Pointcut("execution(public * com.gitee.peterven.controller.admin.*.*(..))")
    • Any method of any class under admin package
  • @Pointcut("execution(public * com.gitee.peterven.controller.admin.AdminController.h*(..))")
    • Methods starting with h under AdminController class

@annotation

Used to match the method with the specified annotation

usage

/** * Annotation on class * @ author wangwenwen * @ date 2021 / 6 / 7 14:43 * @ version v1 zero */@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface AopMethodAnnotation {}
  • @Pointcut("@annotation(com.gitee.peterven.annotation.AopMethodAnnotation)")
    • Used to match methods annotated with AopMethodAnnotation

Args and @ args

They are all used to match the input parameter types, but I tried. They all failed to start. Let's put them first

within

Match the method according to the specified type. Note that it is to match the class, not to match the method

usage

  • @Pointcut("within(com.gitee.peterven.controller.admin.*)")
    • Corresponding methods under the types of all classes under the admin package
  • @Pointcut("within(com.gitee.peterven.controller.admin.AdminController)")
    • All methods under AdminController class
  • @Pointcut("within(com.gitee.peterven.controller.admin.AdminController.*)")
    • This is invalid!!! Please note that

@within

Match the class according to the user-defined annotation to make all the methods under this class enter aop

usage

/**
 * Annotations acting on classes
 * @author wangwenwen
 * @date 2021/6/7 14:43
 * @version v1.0.0
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface AopClassAnnotation {
}
  • @Pointcut("@within(com.gitee.peterven.annotation.AopClassAnnotation)")
    • All methods under the class marked by AopClassAnnotation annotation will be matched

target

Similar to within, but this method can match the target class and its subclasses, while within cannot

/**
 * Public controller
 * @author wangwenwen
 * @date 2021/6/7 14:50
 * @version v1.0.0
 */
public class BaseController {
}

usage

  • @Pointcut("target(com.gitee.peterven.controller.BaseController)")
    • You can match the methods under the BaseController class and its subclasses

@target

I don't know why @ pointcut ("@ target (COM. Gitee. Peteven. Annotation. Aopclassannotation)") failed to start. Let's have a look when you have time.

this

The proxy class matches the specified class by type (the final effect is similar to within())

usage

  • @Pointcut("this(com.gitee.peterven.controller.BaseController)")
    • You can match all the methods under the BaseController class

Reference articles

  • https://blog.csdn.net/qq_33704186/article/details/88413438
  • https://csdnnews.blog.csdn.net/article/details/103231804

Keywords: Java Spring AOP

Added by Clintonio on Mon, 31 Jan 2022 04:20:20 +0200