Spring AOP is based on annotation implementation and details

Table of contents

1. Spring AOP underlying technology

2. Initial implementation of AOP programming

3. Obtain detailed information about the cut-off point

4. Pointcut expression syntax

5. Reuse (extract) pointcut expressions


1. Spring AOP underlying technology

The core of SpringAop lies in dynamic proxy, so what technology does the underlying technology of SpringAop rely on?

  • Dynamic proxy (InvocationHandler): JDK's native implementation method. The target class that needs to be proxied must implement the interface. Because this technology requires the proxy object and the target object to implement the same interface (the two brothers worship the sub pattern).
  • cglib: Implements proxying by inheriting the proxied target class, so the target class does not need to implement the interface.
  • AspectJ: An early AOP implementation framework, Spring AOP borrowed the AOP annotations in AspectJ.

2. Initial implementation of AOP programming

2.1 Implementing AOP requires the following annotations:

annotation illustrate
@SpringJUnitConfig Using Spring test context configuration in JUnit test class
@Aspect Mark the class as an aspect class and define the location of the aspect logic and enhancement methods
@EnableAspectJAutoProxy Turn on AspectJ automatic proxy to enable Spring AOP function

2.2 The following dependencies need to be imported

<!-- 切面实现 -->
 <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>6.0.6</version>
</dependency>
<!-- spring核心 -->
 <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.2.RELEASE</version>
    </dependency>
<!-- spring-test容器测试 -->
 <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>6.0.6</version>
      <scope>test</scope>
    </dependency>

2.3 Enhancement (notification) annotations

annotation illustrate
@Before Enhancement logic executed before the target method is executed
@AfterReturning Enhanced logic executed after the target method returns successfully
@AfterThrowing Enhanced logic executed after the target method throws an exception
@After Enhancement logic that executes after the target method executes
@Around Wrap the target method, and you can execute customized enhanced logic before and after the target method is executed.

Steps to implement enhancements (notifications)

  1. Define methods to store enhancement code
  2. Use annotation configuration to specify the location of the insertion target
  3. Configure the pointcut expression (select the insertion method, pointcut)
  4. Complete the annotation, add it to the ioc container, and set the aspect @Aspect
  5. Enable aspect annotation annotation

Case code:

//4.补全注解
@Component
@Aspect

//1.创建增强类与增强方法start(),after,Error
public class advice {

//    2.使用注解配置,配置插入位置@Before @After @AfterThrowing
//    3.配入切点表达式execution(* com.alphamilk.Impl.*.*(..))表明需要插入的方法为所有com.alhpamilk.Impl包下所有类的所有方法
    @Before("execution(* com.alphamilk.Impl.*.*(..))")
    public void  start(){
        System.out.println("方法起始处插入");
    }

    @After("execution(* com.alphamilk.Impl.*.*(..))")
    public void after(){
        System.out.println("方法结束后插入");
    }
    @AfterThrowing("execution(* com.alphamilk.Impl.*.*(..))")
    public void Error(){
        System.out.println("方法异常时候插入");
    }
}
@ComponentScan(value = "com.alphamilk")
@Configuration
//6.注解类中开启注解注释
@EnableAspectJAutoProxy
public class JavaConfig {
}


3. Obtain detailed information about the cut-off point

Although the implementation of AOP has been initially implemented, it is not enough. When calling multiple methods, if they are all input, before calling the method, after calling the method, etc., this cannot distinguish which method is called, so in order to distinguish we need to obtain Information related to calling this method, such as parameters, method name, return value, etc.

Specific implementation method:
Obtained through the following methods of the JoinPoint interface

method illustrate
getTarget() Get the proxy target object
getClass() Get the class of the proxied target object
getSimpleName() Get the simple class name of the proxied target object (without package name)
getArgs() Get method parameter array
getSignature() Obtain method signature, including method name, return type, parameter type and other information
getModifiers() Get method modifier

There are three cases: general situations, situations where a return value is required, and abnormal situations.

General situation (pre-notification, post-notification)

Case code:

It is necessary to add the JoinPoint interface parameter to the method call to instantiate the object to create the corresponding dynamic proxy, and obtain object-related information through the dynamic proxy.

public class advice {


    @Before("execution(* com.alphamilk.*.*(..))")
    public void Before(JoinPoint joinPoint) {
//        获取类名
        String simpleName = joinPoint.getTarget().getClass().getSimpleName();
//        获取方法修饰符
        int modifiers = joinPoint.getSignature().getModifiers();
        String Moidfier = Modifier.toString(modifiers);
//        获取方法名称
        String name = joinPoint.getSignature().getName();
//        获取参数
        Object[] args = joinPoint.getArgs();
//
        System.out.println("调用的方法是" + name);
        System.out.println("调用的类是" + simpleName);
        for (Object arg : args
        ) {
            System.out.println(arg);
        }
        System.out.println("调用方法前");
    }

    @After("execution(* com.alphamilk.*.*(..))")
    public void After(JoinPoint joinPoint) {
        System.out.println("调用方法后");
    }
}

When there is a return value (return notification)

Under normal circumstances, you need to add more Object result parameters to receive the return value. And add annotations to return to enter the exact name of the returned object.

Case code

public class advice {

    @AfterReturning(value = "execution(* com.alphamilk.*.*(..))",returning = "result")
    public void AfterReturning(JoinPoint joinPoint,Object result) {
        System.out.println("调用拥有返回值的方法");
        System.out.println("获取到的返回值为"+result);
    }
}

Abnormal situations (exception notification)

For exception notification, to obtain exception information, under normal circumstances, you need to declare an additional annotation throwing in the annotation, add a Throwable object to the method parameter, and the value corresponding to the throwing annotation is the object name of Throwable.

Case code:

 @AfterThrowing(value = "execution(* com.alphamilk.*.*(..))",throwing = "throwable")
    public void AfterThrowing(JoinPoint joinPoint,Throwable throwable) {
        System.out.println("调用有异常的方法");
        System.out.println("异常对象为"+throwable.getClass().getName());
    }
@SpringJUnitConfig(value = JavaConfig.class)
public class newaopTest {
    @Autowired
    private Caculate caculate;
    @Test
    public void Test(){
        caculate.div(2,0);
    }
}


4. Pointcut expression syntax

1. Function of point-cut expression

AOP pointcut expression (Pointcut Expression) is a language used to specify pointcuts. It can select the target object that needs to be cut into by defining matching rules.

2. Pointcut expression syntax

  • Specific value:

    • (String, int): The first parameter is a string and the second parameter is an integer.
    • (int, String): The first parameter is an integer and the second parameter is a string.
    • (): No parameters.
  • Fuzzy value:

    • (..): Any parameter, with or without.
  • Partially specific and vague:

    • (String..): The first parameter is a string, followed by other parameters.
    • (..String): The last parameter is a string, there may be other parameters in front.
    • (String..int): The beginning of the string, the last parameter is an integer, and there may be other parameters in the middle.
    • (..int..): Contains parameters of integer type, the position is not limited, and there may be other parameters.

Specific practical cases:

1. Query all methods under a certain package and category whose access modifier is public and whose return value is int.

execution public int a certain package. a certain class.*(..)

2. Query the method whose first parameter is String in a class under a certain package

execution * a certain package. a certain class.*(String..)

3. Query all packages, no parameter method!

execution * *..*.*( )

4. Query the method ending with int parameter type under the COM package

execution * com..*.*(..int)

5. Query the parameterless method of the private return value int of the class starting with Service under the specified package.

execution private int specification package.Service*.*()


5. Reuse (extract) pointcut expressions

If you add a fixed pointcut expression before each method, it will be very troublesome, so the following introduces the reuse of pointcut expressions

1. Extract in the current class

Specific annotation @Pointcut

annotation describe
@Pointcut Method for declaring pointcut expressions, used to define matching rules for pointcuts.

By defining an empty method, use the @Pointcut annotation with a specific pointcut expression

Case code:

@Component
@Aspect
public class advice {
    
    /*
    定义空方法
    空方法上加上注解@Pointcut并带上相应的切点表达式
    在其他增强方法上调用方法
     */
    @Pointcut("execution(* com.alphamilk.*.*(..))" )
    public void blank(){}

  @Before("blank()")
    public void Before(JoinPoint joinPoint) {
        System.out.println("调用方法前");
    }

 @After("blank()")
    public void After(JoinPoint joinPoint) {
        System.out.println("调用方法后");
    }

    @AfterReturning(value = "blank()",returning = "result")
    public void AfterReturning(JoinPoint joinPoint,Object result) {
        System.out.println("调用拥有返回值的方法");
    }

    @AfterThrowing(value = "blank()",throwing = "throwable")
    public void AfterThrowing(JoinPoint joinPoint,Throwable throwable) {
        System.out.println("调用有异常的方法");
    }
}

2. Create a storage pointcut class

(Recommended) Make it easier to maintain expressions by creating a separate class that stores pointcuts

  Just add the method name of a specific class when using it

Case:

Class to store pointcuts

@Component
public class MyPointcut {
    @Pointcut("execution(* com.alphamilk.Impl.*.*(..))")
    public void pointcut1(){}
}

Corresponding reference class

@Component
@Aspect
public class advice {
  @Before("com.alphamilk.Advice.MyPointcut.pointcut1()")
    public void Before(JoinPoint joinPoint) {
        System.out.println("调用方法前");
    }

 @After("com.alphamilk.Advice.MyPointcut.pointcut1()")
    public void After(JoinPoint joinPoint) {
        System.out.println("调用方法后");
    }

    @AfterReturning(value = "com.alphamilk.Advice.MyPointcut.pointcut1()",returning = "result")
    public void AfterReturning(JoinPoint joinPoint,Object result) {
        System.out.println("调用拥有返回值的方法");
    }

    @AfterThrowing(value = "com.alphamilk.Advice.MyPointcut.pointcut1()",throwing = "throwable")
    public void AfterThrowing(JoinPoint joinPoint,Throwable throwable) {
        System.out.println("调用有异常的方法");
    }
}

Chapter summary

1.SpringAop underlying technology

        Understand the underlying proxy technologies including jdk and cglib

2. Preliminary implementation of AOP programming

        Master enhanced annotations (@Before, @AfterReturning, @AfterThrowing, @After, @Around)

        Master the use of @Aspect annotation

3. Obtain detailed information about the cut-off point

        Master how to obtain the class, method name, parameters, and method modifiers of the corresponding method through the JoinPoint interface object

        Master the situation of obtaining corresponding information in three different situations (general situation, return notification, exception notification)

4. Pointcut expression syntax

        Be familiar with the format of pointcut expressions

      (execution + permission modification + method return value type + full class name of the method + method name + parameter list)

5. Reuse (extract) pointcut expressions

        

Guess you like

Origin blog.csdn.net/dogxixi/article/details/132521385