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(..) 的参数顺序必须遵循:
- 如果使用了
this()绑定,第一个参数必须是 this 对象 - 如果使用了
target()绑定,第二个参数必须是 target 对象 - 最后是连接点的所有参数 (按原始顺序)
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() | Class | DeclareParents.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.Type 和 java.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 | 成员签名的基础接口 |
CatchClauseSignature | catch 子句签名 |
InitializerSignature | 静态/实例初始化块签名 |
LockSignature | synchronized 锁获取签名 |
UnlockSignature | synchronized 锁释放签名 |
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 | 方面访问工具类 |
| 类 | Aspects14 | Java 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 包
| 类型 | 名称 | 说明 |
|---|---|---|
| 接口 | AjType | AspectJ 类型表示 |
| 接口 | AjTypeSystem | AspectJ 类型系统入口 |
| 接口 | SourceLocation | 源代码位置 |
| 接口 | CodeSignature | 代码签名 |
| 接口 | MemberSignature | 成员签名 |
| 接口 | MethodSignature | 方法签名 |
| 接口 | ConstructorSignature | 构造函数签名 |
| 接口 | FieldSignature | 字段签名 |
| 接口 | AdviceSignature | 通知签名 |
| 接口 | InitializerSignature | 初始化块签名 |
| 接口 | LockSignature | 锁签名 |
| 接口 | UnlockSignature | 解锁签名 |
| 接口 | CatchClauseSignature | Catch 子句签名 |
| 接口 | PerClause | Per-clause 表示 |
| 接口 | PerClauseKind | Per-clause 类型枚举 |
| 接口 | Pointcut | 切点对象 |
| 接口 | PointcutExpression | 表达式切点 |
| 接口 | TypePattern | 类型模式切点 |
| 接口 | Advice | 通知对象 |
| 接口 | AdviceKind | 通知类型枚举 |
| 接口 | InterTypeDeclaration | Inter-type 声明 |
| 接口 | InterTypeMethodDeclaration | 方法引入 |
| 接口 | InterTypeFieldDeclaration | 字段引入 |
| 接口 | InterTypeConstructorDeclaration | 构造函数引入 |
| 接口 | DeclareErrorOrWarning | Declare error/warning |
| 接口 | DeclareParents | Declare parents |
| 接口 | DeclareSoft | Declare soft |
| 接口 | DeclareAnnotation | Declare annotation |
| 接口 | DeclarePrecedence | Declare 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
