Skip to content

SpringAop详解

约 1468 字大约 5 分钟

Spring源码

2024-12-25

一、术语解释

@Aspect(切面)

@Pointcut(切点)

1、AspectJ切入点指示符

切入点指示符用来指示切入点表达式目的,在Spring AOP中目前只有执行方法这一个连接点,Spring AOP支持的AspectJ切入点指示符如下:

  • execution:用于匹配方法执行的连接点

  • within:用于匹配指定类型内的方法执行

  • this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配

  • target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配

  • args:用于匹配当前执行的方法传入的参数为指定类型的执行方法

  • @within:用于匹配所以持有指定注解类型内的方法

  • @target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解

  • @args:用于匹配当前执行的方法传入的参数持有指定注解的执行

  • @annotation:用于匹配当前执行方法持有指定注解的方法

  • bean:Spring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法

2、类型匹配语法

类型匹配语法

*:匹配任何数量字符;

..:匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。

+:匹配指定类型的子类型;仅能作为后缀放在类型模式后边。

使用示例

java.lang.String    匹配String类型;  

java.*.String       匹配java包下的任何“一级子包”下的String类型;  
如匹配java.lang.String,但不匹配java.lang.ss.String  

java..*            匹配java包及任何子包下的任何类型;  
                   如匹配java.lang.Stringjava.lang.annotation.Annotation  
                   
java.lang.*ing      匹配任何java.lang包下的以ing结尾的类型

java.lang.Number+  匹配java.lang包下的任何Number的自类型
                   如匹配java.lang.Integer,也匹配java.math.BigInteger

Advice(通知)

通知类型术语解释描述
@Before前置通知用于定义前置通知,在目标方法执行前执行额外的逻辑。前置通知通常用于在方法执行前做一些准备工作,例如参数验证或日志记录。
@AfterReturning后置通知用于定义后置通知,在目标方法成功执行后执行额外的逻辑。通常用于处理方法的返回值或执行清理工作。发生异常便不会执行
@AfterThrowing异常通知用于定义异常通知,它在目标方法抛出异常时执行额外的逻辑。异常通知通常用于记录异常信息或处理异常情况。
@After最终通知用于定义最终通知,它在目标方法执行后(不论是否发生异常)执行额外的逻辑。最终通知通常用于执行清理工作,例如释放资源。
@Around环绕通知用于定义环绕通知,它能够完全控制目标方法的执行。环绕通知可以在方法执行前、执行中和执行后执行额外逻辑,它需要显式地调用 ProceedingJoinPoint.proceed() 方法来控制目标方法的执行。

二、通知参数

如果想获取被被通知方法参数并传递给通知方法,该如何实现呢?接下来我们将介绍两种获取通知参数的方式。

1. JoinPoint: 提供访问当前被通知方法的目标对象、代理对象、方法参数等数据

package org.aspectj.lang;  
import org.aspectj.lang.reflect.SourceLocation;  
public interface JoinPoint {  
    String toString();         //连接点所在位置的相关信息  
    String toShortString();     //连接点所在位置的简短相关信息  
    String toLongString();     //连接点所在位置的全部相关信息  
    Object getThis();         //返回AOP代理对象  
    Object getTarget();       //返回目标对象  
    Object[] getArgs();       //返回被通知方法参数列表  
    Signature getSignature();  //返回当前连接点签名  
    SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置  
    String getKind();        //连接点类型  
    StaticPart getStaticPart(); //返回连接点静态部分  
}

常用API:

方法名描述
getSignature()获取目标方法的方法名、参数类型、返回类型及Class等信息
getArgs()获取传入目标方法的参数值
getTarget()获取被代理的对象
getThis()获取代理对象

2. ProceedingJoinPoint: 用于环绕通知,使用proceed()方法来执行目标方法:

public interface ProceedingJoinPoint extends JoinPoint {  
    public Object proceed() throws Throwable;  //执行目标方法
    public Object proceed(Object[] args) throws Throwable; //传入新的参数执行目标方法
}

常用API:

方法名描述
proceed()执行目标方法
proceed(Object[] args)传入新的参数执行目标方法

3. JoinPoint.StaticPart: 提供访问连接点的静态部分,如被通知方法签名、连接点类型等

public interface StaticPart {  
    Signature getSignature();    //返回当前连接点签名  
    String getKind();          //连接点类型  
    int getId();               //唯一标识  
    String toString();         //连接点所在位置的相关信息  
    String toShortString();     //连接点所在位置的简短相关信息  
    String toLongString();     //连接点所在位置的全部相关信息  
}

提示

  • JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象。
  • ProceedingJoinPoint对象是JoinPoint的子接口,该对象只能用于@Around的环绕切面方法中。

参考

1.SpringAOP(图文详解)

2.Spring——AOP原理及流程详解

3.Spring AOP + 异步任务实现日志记录(操作日志、异常日志)参考ruoyi

4.

Power by VuePress & vuepress-theme-plume