Skip to content

AspectJ org.aspectj.lang 包详解

依赖信息:

xml
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.25.1</version>
</dependency>

检索日期: 2026-08-05


1. 概述

AspectJ 是一个面向方面编程 (AOP) 框架,扩展了 Java 语言,提供了强大的模块化能力。org.aspectj.lang 包是 AspectJ 运行时的核心 API 包,提供了连接点 (JoinPoint)、签名 (Signature)、源代码位置 (SourceLocation) 等核心接口,以及注解支持。

包结构:

org.aspectj.lang
├── annotation/          # 注解类型 (@Aspect, @Before, @After 等)
├── reflect/             # 反射接口 (MethodSignature, FieldSignature 等)
├── internal/            # 内部实现 (不公开使用)
└── [核心类与接口]

2. 核心接口

2.1 JoinPoint (连接点)

作用: 提供对连接点状态和静态信息的反射访问。在 Advice 体内通过 thisJoinPoint 访问。

主要方法:

方法返回值说明
getThis()Object当前执行对象 (与 this() 切点匹配的对象相同)
getTarget()Object目标对象 (与 target() 切点匹配的对象相同)
getArgs()Object[]连接点的参数数组
getSignature()Signature连接点的签名
getSourceLocation()SourceLocation连接点的源代码位置
getKind()String连接点类型 (如 "method-execution")
getStaticPart()StaticPart获取连接点的静态部分

内置常量 (连接点类型):

java
String METHOD_EXECUTION = "method-execution";
String METHOD_CALL = "method-call";
String CONSTRUCTOR_EXECUTION = "constructor-execution";
String CONSTRUCTOR_CALL = "constructor-call";
String FIELD_GET = "field-get";
String FIELD_SET = "field-set";
String STATICINITIALIZATION = "staticinitialization";
String INITIALIZATION = "initialization";
String EXCEPTION_HANDLER = "exception-handler";
String SYNCHRONIZATION_LOCK = "lock";
String SYNCHRONIZATION_UNLOCK = "unlock";
String ADVICE_EXECUTION = "adviceexecution";

使用示例:

java
@Aspect
public class Logging {
    @Before("within(com.bigboxco..*) && execution(public * *(..))")
    public void logEntry(JoinPoint thisJoinPoint) {
        System.err.println("entering: " + thisJoinPoint);
        System.err.println("  w/args: " + Arrays.toString(thisJoinPoint.getArgs()));
        System.err.println("      at: " + thisJoinPoint.getSourceLocation());
    }
}

2.2 JoinPoint.StaticPart (静态部分)

作用: 封装连接点的静态信息,可通过 thisJoinPointStaticPart 访问。相比完整的 JoinPoint,StaticPart 占用更少的内存且性能更好。

主要方法:

方法返回值说明
getSignature()Signature连接点签名
getSourceLocation()SourceLocation源代码位置
getKind()String连接点类型
getId()int连接点静态部分的唯一 ID

特点:

  • ID 在程序多次执行间保持不变 (但重新编译后可能变化)
  • 可用于数组索引优化 (比 Map 查找更快)

2.3 JoinPoint.EnclosingStaticPart

作用: 表示外围静态部分的接口,继承自 StaticPart。用于获取包围当前连接点的外围连接点信息。


2.4 ProceedingJoinPoint (可继续的连接点)

作用: 扩展 JoinPoint 接口,专为 @Around 环绕通知设计,提供 proceed() 方法以继续执行下一个通知或目标方法。

主要方法:

方法说明
proceed()执行下一个通知或目标方法,返回执行结果
proceed(Object[] args)使用新参数执行下一个通知或目标方法

使用示例:

java
@Around("execution(* com.example.service.*.*(..))")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
    System.out.println("Before: " + pjp.getSignature().getName());
    try {
        Object result = pjp.proceed();  // 执行目标方法
        System.out.println("After returning: " + result);
        return result;
    } catch (Throwable t) {
        System.out.println("After throwing: " + t.getMessage());
        throw t;
    }
}

注意: 在注解风格中,proceed(..) 的参数顺序必须遵循:

  1. 如果使用了 this() 绑定,第一个参数必须是 this 对象
  2. 如果使用了 target() 绑定,第二个参数必须是 target 对象
  3. 最后是连接点的所有参数 (按原始顺序)

2.5 Signature (签名)

作用: 表示连接点的签名,类似于 java.lang.reflect.Member 接口。

主要方法:

方法返回值说明
getName()String签名的标识符 (如方法名)
getModifiers()int修饰符 (可用 Modifier 工具类解析)
getDeclaringType()Class声明该成员的类、接口或方面
getDeclaringTypeName()String声明类型的完全限定名 (已缓存)

子接口:

  • MemberSignature: 成员签名的基础接口
  • CodeSignature: 代码签名 (含参数信息)
  • MethodSignature: 方法签名
  • ConstructorSignature: 构造函数签名
  • FieldSignature: 字段签名
  • AdviceSignature: 通知签名
  • InitializerSignature: 初始化块签名
  • LockSignature: 锁签名
  • UnlockSignature: 解锁签名
  • CatchClauseSignature: catch 子句签名

2.6 CodeSignature (代码签名)

作用: 扩展 MemberSignature,提供方法/构造函数的参数和异常信息。

主要方法:

java
Class[] getParameterTypes();   // 参数类型数组
String[] getParameterNames();  // 参数名称数组
Class[] getExceptionTypes();   // 声明的异常类型数组

2.7 MethodSignature (方法签名)

作用: 扩展 CodeSignature,提供方法特有的反射信息。

主要方法:

java
Class getReturnType();   // 返回类型
Method getMethod();      // Java Method 对象

2.8 ConstructorSignature (构造函数签名)

作用: 扩展 CodeSignature,提供构造函数特有的反射信息。

主要方法:

java
Constructor getConstructor();  // Java Constructor 对象

2.9 FieldSignature (字段签名)

作用: 扩展 MemberSignature,提供字段特有的反射信息。

主要方法:

java
Class getFieldType();  // 字段类型
Field getField();      // Java Field 对象

2.10 AdviceSignature (通知签名)

作用: 扩展 CodeSignature,表示通知的签名。

主要方法:

java
Class getReturnType();  // 返回类型 (before/after 为 Void.TYPE)
Method getAdvice();     // 通知方法对象

2.11 SourceLocation (源代码位置)

作用: 定义代码、被定义的类和源文件中的位置。

主要方法:

方法返回值说明
getWithinType()Class获取定义该连接点的类型
getFileName()String源文件名
getLine()int行号
getColumn()int列号 (已过时,字节码织入无法实现)

使用示例:

java
@AfterThrowing(pointcut = "execution(* com.example..*.*(..))", throwing = "ex")
public void logException(JoinPoint jp, Throwable ex) {
    SourceLocation loc = jp.getSourceLocation();
    System.out.println("Exception at " + loc.getFileName() 
                       + ":" + loc.getLine());
}

3. 注解类型 (org.aspectj.lang.annotation)

3.1 @Aspect

作用: 声明一个方面类。

属性:

属性类型默认值说明
value()String""per-clause 表达式 (如 "perthis(this())"、"pertarget(target())"),空表示单例方面

使用示例:

java
@Aspect  // 单例方面
public class LoggingAspect { ... }

@Aspect("perthis(execution(* com.example.service.*.*(..)))")
public class PerObjectAspect { ... }

3.2 @Before

作用: 声明前置通知,在匹配的连接点之前执行。

属性:

属性类型默认值说明
value()String-切点表达式 (必填)
argNames()String""参数名列表 (逗号分隔),仅在无调试信息时需要

使用示例:

java
@Before("execution(* com.example.service.*.*(..)) && args(userId,..)")
public void beforeMethod(JoinPoint jp, String userId) {
    System.out.println("Before method with userId: " + userId);
}

3.3 @After

作用: 声明后置通知 (finally 块风格),无论连接点正常返回还是抛出异常都会执行。

属性:

属性类型默认值说明
value()String-切点表达式
argNames()String""参数名列表

使用示例:

java
@After("execution(* com.example.repository.*.*(..))")
public void afterMethod(JoinPoint jp) {
    System.out.println("After method: " + jp.getSignature().getName());
}

3.4 @AfterReturning

作用: 声明返回通知,在连接点正常返回后执行。

属性:

属性类型默认值说明
value()String""切点表达式
pointcut()String""切点表达式 (优先级高于 value)
returning()String""绑定返回值到通知方法的参数名
argNames()String""参数名列表

使用示例:

java
@AfterReturning(
    pointcut = "execution(* com.example.service.*.*(..))",
    returning = "result"
)
public void afterReturning(JoinPoint jp, Object result) {
    System.out.println("Method returned: " + result);
}

3.5 @AfterThrowing

作用: 声明异常通知,在连接点抛出异常后执行。

属性:

属性类型默认值说明
value()String""切点表达式
pointcut()String""切点表达式 (优先级高于 value)
throwing()String""绑定抛出的异常到通知方法的参数名
argNames()String""参数名列表

使用示例:

java
@AfterThrowing(
    pointcut = "execution(* com.example.service.*.*(..))",
    throwing = "ex"
)
public void afterThrowing(JoinPoint jp, Throwable ex) {
    System.err.println("Method threw exception: " + ex.getMessage());
}

3.6 @Around

作用: 声明环绕通知,可以控制连接点的执行,是最强大的通知类型。

属性:

属性类型默认值说明
value()String-切点表达式
argNames()String""参数名列表

使用示例:

java
@Around("execution(* com.example.service.*.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
    long start = System.currentTimeMillis();
    try {
        Object result = pjp.proceed();
        long duration = System.currentTimeMillis() - start;
        System.out.println("Method executed in " + duration + "ms");
        return result;
    } catch (Throwable t) {
        System.err.println("Method threw exception: " + t);
        throw t;
    }
}

3.7 @Pointcut

作用: 声明一个切点,可以被其他注解引用。

属性:

属性类型默认值说明
value()String""切点表达式 (抽象切点可为空)
argNames()String""参数名列表

使用示例:

java
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}

@Pointcut("within(com.example..*)")
public void inExamplePackage() {}

// 引用其他切点
@Before("serviceMethods() && inExamplePackage()")
public void beforeService(JoinPoint jp) { ... }

3.8 @DeclareParents

作用: 声明引入 (Introduction),向现有类型添加新的父类 (Mixin 模式)。

属性:

属性类型默认值说明
value()String-目标类型表达式 (必填)
defaultImpl()ClassDeclareParents.class接口的默认实现类

使用示例:

java
@Aspect
public class IntroductionAspect {
    
    @DeclareParents(value = "com.example.service.*", defaultImpl = AuditableImpl.class)
    public static Auditable auditableMixin;
}

// 被引入的接口
public interface Auditable {
    void audit();
}

// 默认实现
public class AuditableImpl implements Auditable {
    public void audit() {
        System.out.println("Auditing...");
    }
}

3.9 @DeclareMixin

作用: 通过工厂方法声明引入 (Inter-type Declaration),向匹配的类型混合新方法。

属性:

属性类型默认值说明
value()String-目标类型表达式
interfaces()Class[]要混合入的接口数组 (可选)

使用示例:

java
@Aspect
public class MixinAspect {
    
    @DeclareMixin("com.example.entity.*")
    public static Identifiable createIdentifiable() {
        return new IdentifiableImpl();
    }
}

3.10 @DeclareError

作用: 在编译时或织入时对匹配的连接点报告错误。

属性:

属性类型默认值说明
value()String-切点表达式

使用示例:

java
@Aspect
public class EnforceArchitecture {
    
    @DeclareError("call(* com.example.dao.*.*(..)) && within(com.example.ui..*)")
    private static final String UI_CANNOT_CALL_DAO = 
        "UI layer cannot directly call DAO layer!";
}

3.11 @DeclareWarning

作用: 在编译时或织入时对匹配的连接点报告警告。

属性:

属性类型默认值说明
value()String-切点表达式

使用示例:

java
@Aspect
public class PerformanceWarnings {
    
    @DeclareWarning("call(* java.lang.System.gc())")
    private static final String DO_NOT_CALL_GC = 
        "Explicit GC calls are discouraged!";
}

3.12 @DeclarePrecedence

作用: 声明方面的优先级,控制多个方面应用到同一连接点时的执行顺序。

属性:

属性类型默认值说明
value()String-优先级模式列表 (逗号分隔)

使用示例:

java
@Aspect
@DeclarePrecedence("SecurityAspect, LoggingAspect, *")
public class TransactionAspect { ... }

解释: SecurityAspect 最先执行,然后是 LoggingAspect,最后是其他所有方面 (*)。


3.13 @SuppressAjWarnings

作用: 抑制 AspectJ 编译器对特定代码区域的警告。


3.14 @AdviceName

作用: 为代码风格的通知声明指定名称,可通过 JoinPoint.getSignature().getName() 获取。

使用示例:

java
@Around("execution(* com.example.service.*.*(..))")
@AdviceName("ServiceExecutionMonitor")
public Object monitor(ProceedingJoinPoint pjp) throws Throwable { ... }

3.15 @RequiredTypes

作用: 指定方面编译时所需的类型约束。


3.16 AnnotationBinding (内部使用)

作用: 注解绑定的内部表示 (非公开 API)。


4. 反射类型 (org.aspectj.lang.reflect)

4.1 AjType

作用: AspectJ 程序中类型 (方面、类、接口、注解、枚举、数组) 的运行时表示,扩展了 java.lang.reflect.Typejava.lang.reflect.AnnotatedElement

主要方法分类:

基础信息:

java
String getName();                    // 类型名称
Package getPackage();                // 所在包
AjType<?>[] getInterfaces();         // 实现的接口
int getModifiers();                  // 修饰符
Class<T> getJavaClass();             // 对应的 Java Class

继承关系:

java
AjType<?> getSupertype();            // 父类/超类型
Type getGenericSupertype();          // 泛型超类型

内部类型:

java
AjType<?>[] getAjTypes();            // 所有成员类型
AjType<?>[] getDeclaredAjTypes();    // 声明的成员类型

构造器:

java
Constructor getConstructor(AjType<?>... parameterTypes);
Constructor[] getConstructors();
Constructor getDeclaredConstructor(AjType<?>... parameterTypes);
Constructor[] getDeclaredConstructors();

字段:

java
Field getDeclaredField(String name);
Field[] getDeclaredFields();
Field getField(String name);
Field[] getFields();

方法:

java
Method getDeclaredMethod(String name, AjType<?>... parameterTypes);
Method getMethod(String name, AjType<?>... parameterTypes);
Method[] getDeclaredMethods();
Method[] getMethods();

切点 (AspectJ 特有):

java
Pointcut getDeclaredPointcut(String name);
Pointcut[] getDeclaredPointcuts();
Pointcut getPointcut(String name);
Pointcut[] getPointcuts();

通知 (AspectJ 特有):

java
Advice[] getDeclaredAdvice(AdviceKind... ofTypes);
Advice[] getAdvice(AdviceKind... ofTypes);
Advice getAdvice(String name);

** inter-type 声明 (AspectJ 特有)**:

java
InterTypeMethodDeclaration[] getDeclaredITDMethods();
InterTypeFieldDeclaration[] getDeclaredITDFields();
InterTypeConstructorDeclaration[] getDeclaredITDConstructors();

declare 语句:

java
DeclareErrorOrWarning[] getDeclareErrorOrWarnings();
DeclareParents[] getDeclareParents();
DeclareSoft[] getDeclareSofts();
DeclareAnnotation[] getDeclareAnnotations();
DeclarePrecedence[] getDeclarePrecedence();

类型判断:

java
boolean isEnum();
boolean isInterface();
boolean isArray();
boolean isPrimitive();
boolean isAspect();           // 是否为方面类型
boolean isMemberAspect();     // 是否为成员方面
boolean isPrivileged();       // 是否为特权方面

4.2 AjTypeSystem

作用: AspectJ 类型系统的入口点,用于获取 AjType 实例。

主要方法:

java
// 将 Java Class 转换为 AjType
public static AjType<?> getAjType(Class<?> clazz);

// 清除缓存
public static void clearCache();

4.3 PerClause

作用: 表示与方面关联的 per-clause (方面实例化模型)。

主要方法:

java
PerClauseKind getKind();  // 返回 per-clause 类型

PerClauseKind 枚举值:

  • Singleton: 单例方面 (默认)
  • PerThis: 每个 this 对象一个实例
  • PerTarget: 每个 target 对象一个实例
  • PerTypeWithin: 每个类型内一个实例
  • PerControlFlow: 每个控制流一个实例 (percflow)
  • PerControlFlowBelow: 每个控制流下方一个实例 (percflowbelow)

4.4 Pointcut

作用: 表示运行时切点对象。

子类型:

  • PointcutExpression: 基于表达式的切点
  • TypePattern: 基于类型模式的切点

4.5 Advice

作用: 表示运行时通知对象。

相关枚举 AdviceKind:

  • Before: 前置通知
  • After: 后置通知
  • AfterReturning: 返回通知
  • AfterThrowing: 异常通知
  • Around: 环绕通知

4.6 InterTypeDeclaration (ITD)

作用: 表示 inter-type 声明 (引入) 的运行时表示。

子类型:

  • InterTypeMethodDeclaration: 方法引入
  • InterTypeFieldDeclaration: 字段引入
  • InterTypeConstructorDeclaration: 构造函数引入

4.7 DeclareErrorOrWarning

作用: 表示 declare error/warning 声明的运行时表示。

子类型:

  • DeclareError: 编译时错误声明
  • DeclareWarning: 编译时警告声明
  • DeclareSoft: 软异常声明

4.8 DeclareParents

作用: 表示 declare parents 引入的运行时表示。


4.9 DeclareAnnotation

作用: 表示 declare annotation 引入的运行时表示。

内部枚举 DeclareAnnotation.Kind:

  • TYPE: 类型注解
  • FIELD: 字段注解
  • METHOD: 方法注解

4.10 DeclarePrecedence

作用: 表示 declare precedence 声明的运行时表示。


4.11 其他反射接口

接口说明
MemberSignature成员签名的基础接口
CatchClauseSignaturecatch 子句签名
InitializerSignature静态/实例初始化块签名
LockSignaturesynchronized 锁获取签名
UnlockSignaturesynchronized 锁释放签名
TypePatternBasedPerClause基于类型模式的 per-clause
PointcutBasedPerClause基于切点的 per-clause

5. 异常类

5.1 NoAspectBoundException

作用: 当调用 aspectOf() 方法但没有找到绑定的方面实例时抛出。

java
public class NoAspectBoundException extends RuntimeException {
    public NoAspectBoundException(String aspectName, Throwable inner);
    public NoAspectBoundException();
    public Throwable getCause();
}

使用场景:

java
try {
    MyAspect aspect = MyAspect.aspectOf();
} catch (NoAspectBoundException e) {
    System.out.println("No aspect instance bound!");
}

5.2 SoftException

作用: 包装被 declare soft 软化的受检异常,使其作为非受检异常抛出。

java
public class SoftException extends RuntimeException {
    private Throwable inner;
    
    public SoftException(Throwable inner);
    public Throwable getWrappedThrowable();
    public Throwable getCause();
}

使用示例:

java
// 在方面中声明
declare soft : IOException : execution(* com.example.service.*.*(..));

// 这样 IOException 就不需要显式捕获或声明了

5.3 NoSuchPointcutException

作用: 当请求的切点不存在时抛出。


5.4 NoSuchAdviceException

作用: 当请求的通知不存在时抛出。


6. 工具类

6.1 Aspects

作用: 提供通用方法来访问方面的 aspectOf()hasAspect() 方法,特别适用于负载期织入 (LTW) 场景。

主要方法:

获取方面实例:

java
// 单例或 per-thread/per-cflow 方面
public static <T> T aspectOf(Class<T> aspectClass);

// perthis/pertarget 方面
public static <T> T aspectOf(Class<T> aspectClass, Object perObject);

// pertypewithin 方面
public static <T> T aspectOf(Class<T> aspectClass, Class<?> perTypeWithin);

检查方面是否存在:

java
public static boolean hasAspect(Class<?> aspectClass);
public static boolean hasAspect(Class<?> aspectClass, Object perObject);
public static boolean hasAspect(Class<?> aspectClass, Class<?> perTypeWithin);

使用示例:

java
// 替代直接调用 aspectOf()
MyAspect aspect = Aspects.aspectOf(MyAspect.class);

if (Aspects.hasAspect(MyAspect.class)) {
    MyAspect aspect = Aspects.aspectOf(MyAspect.class);
    // 使用方面
}

6.2 Aspects14

作用: 针对 Java 1.4 兼容的方面访问工具类 (已过时)。


7. 内部类 (不推荐使用)

7.1 PlaceHolder

: org.aspectj.lang.internal.lang

作用: 编译器内部使用的占位符类,不应在用户代码中直接使用。


7.2 CodeGenerationHint

: org.aspectj.lang.annotation.control

作用: 控制代码生成的提示注解 (内部使用)。


8. 完整类/接口清单

org.aspectj.lang 包

类型名称说明
接口JoinPoint连接点接口
接口JoinPoint.StaticPart连接点静态部分
接口JoinPoint.EnclosingStaticPart外围静态部分
接口ProceedingJoinPoint可继续的连接点 (用于@Around)
接口Signature签名接口
SoftException软异常包装类
NoAspectBoundException方面未绑定异常
Aspects方面访问工具类
Aspects14Java 1.4 兼容工具类 (过时)

org.aspectj.lang.annotation 包

类型名称说明
注解@Aspect方面声明
注解@Before前置通知
注解@After后置通知
注解@AfterReturning返回通知
注解@AfterThrowing异常通知
注解@Around环绕通知
注解@Pointcut切点声明
注解@DeclareParents声明父类引入
注解@DeclareMixin声明混合入
注解@DeclareError声明错误
注解@DeclareWarning声明警告
注解@DeclarePrecedence声明优先级
注解@SuppressAjWarnings抑制警告
注解@AdviceName通知命名
注解@RequiredTypes所需类型约束

org.aspectj.lang.reflect 包

类型名称说明
接口AjTypeAspectJ 类型表示
接口AjTypeSystemAspectJ 类型系统入口
接口SourceLocation源代码位置
接口CodeSignature代码签名
接口MemberSignature成员签名
接口MethodSignature方法签名
接口ConstructorSignature构造函数签名
接口FieldSignature字段签名
接口AdviceSignature通知签名
接口InitializerSignature初始化块签名
接口LockSignature锁签名
接口UnlockSignature解锁签名
接口CatchClauseSignatureCatch 子句签名
接口PerClausePer-clause 表示
接口PerClauseKindPer-clause 类型枚举
接口Pointcut切点对象
接口PointcutExpression表达式切点
接口TypePattern类型模式切点
接口Advice通知对象
接口AdviceKind通知类型枚举
接口InterTypeDeclarationInter-type 声明
接口InterTypeMethodDeclaration方法引入
接口InterTypeFieldDeclaration字段引入
接口InterTypeConstructorDeclaration构造函数引入
接口DeclareErrorOrWarningDeclare error/warning
接口DeclareParentsDeclare parents
接口DeclareSoftDeclare soft
接口DeclareAnnotationDeclare annotation
接口DeclarePrecedenceDeclare precedence
NoSuchPointcutException切点不存在异常
NoSuchAdviceException通知不存在异常

9. 最佳实践

9.1 切点复用

java
// 定义可复用的切点
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayer() {}

@Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
public void transactional() {}

// 组合使用
@Before("serviceLayer() && !transactional()")
public void warnNonTransactional(JoinPoint jp) { ... }

9.2 参数绑定

java
// 按参数名绑定
@Before("execution(* *.*(.., String email, ..)) && args(email)")
public void logEmail(JoinPoint jp, String email) { ... }

// 按注解绑定
@Before("@annotation(auditLog) && args(request,..)")
public void audit(JoinPoint jp, AuditLog auditLog, Request request) { ... }

9.3 避免过度使用 Around

java
// 优先选择更简单的通知类型
@Before     // 仅前置逻辑
@After      // 清理逻辑 (类似 finally)
@AfterReturning  // 处理返回值
@AfterThrowing // 处理异常

// 只有在需要控制执行流程时才用@Around
@Around     // 最强大但也最复杂

9.4 性能考虑

java
// 使用 StaticPart 代替完整 JoinPoint (仅需静态信息时)
@Before("execution(* com.example..*.*(..))")
public void logStatic(JoinPoint.StaticPart jpStatic) {
    // 性能更好,内存占用更小
    System.out.println(jpStatic.getSignature());
}

参考来源

[1] AspectJ Official Documentation — https://www.eclipse.org/aspectj/
[2] Eclipse AspectJ GitHub — https://github.com/eclipse-aspectj/aspectj
[3] AspectJ Runtime API Javadoc — https://www.javadoc.io/doc/org.aspectj/aspectjrt/latest/
[4] Spring AOP 与 AspectJ 对比 — https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop


更新于:

note