我们来深入分析 @Around 通知的执行逻辑,包括:
@Around背后的动态代理逻辑ProceedingJoinPoint是如何封装目标方法的- 执行链(advice chain)是怎么组织的
🔧 1. Spring AOP 背后的代理实现
Spring AOP 默认使用 JDK 动态代理(接口) 或 CGLIB 代理(子类):
| 目标类类型 | 代理方式 |
|---|---|
| 实现了接口 | JDK 动态代理 |
| 没有接口实现 | CGLIB 子类代理 |
你举的 UserServiceAopProxy extends UserService 就类似 CGLIB 的方式。
📍 2. @Around 是如何工作的
Spring AOP 的 @Around 是基于 责任链模式,核心逻辑是通过 MethodInterceptor 接口实现的。
例子:定义一个 @Around 方法
@Aspect
@Component
public class LoggingAspect {
@Around("execution(* com.example.service.UserService.*(..))")
public Object doLog(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("Before method: " + pjp.getSignature());
Object result = pjp.proceed(); // 目标方法执行
System.out.println("After method: " + pjp.getSignature());
return result;
}
}
🧵 3. 动态代理执行流程细节
以 CGLIB 为例,Spring 会在运行时为你的目标类生成一个子类(即代理类),代理类会拦截所有 public 方法,并执行拦截器链:
public class UserService$$EnhancerBySpringCGLIB extends UserService {
// 拦截所有方法
public User login(String email, String password) {
Method method = ... // 反射获取login方法
MethodInterceptor interceptor = ... // 从缓存中获取Advice链
return (User) interceptor.invoke(new CglibMethodInvocation(this, method, args));
}
}
🔁 4. ProceedingJoinPoint 是如何工作的?
核心类:ReflectiveMethodInvocation(JDK 代理)或 CglibMethodInvocation(CGLIB)
这两个类实现了 ProceedingJoinPoint 接口,其职责是:
- 封装目标方法调用所需的信息(目标对象、方法、参数、注解等)
- 提供
proceed()方法来按顺序执行通知链
内部结构简化如下:
public class ReflectiveMethodInvocation implements ProceedingJoinPoint {
private Object target; // 目标对象
private Method method; // 调用的方法
private Object[] arguments; // 方法参数
private List<MethodInterceptor> interceptors;
private int currentInterceptorIndex = -1;
public Object proceed() throws Throwable {
if (++currentInterceptorIndex == interceptors.size()) {
// 所有Advice执行完,调用目标方法
return method.invoke(target, arguments);
}
// 执行下一个Advice
MethodInterceptor nextInterceptor = interceptors.get(currentInterceptorIndex);
return nextInterceptor.invoke(this); // 递归调用
}
}
你可以理解为:
@Around1 -> @Around2 -> @Before -> method -> @AfterReturning
每个 interceptor 都包裹住下一层,最终最内层调用的是目标方法。
✨ 举例说明
设想你有两个 @Around 通知:
@Around("...") // First
public Object advice1(ProceedingJoinPoint pjp) {
System.out.println("Advice 1 before");
Object result = pjp.proceed(); // 调用下一个拦截器或目标方法
System.out.println("Advice 1 after");
return result;
}
@Around("...") // Second
public Object advice2(ProceedingJoinPoint pjp) {
System.out.println("Advice 2 before");
Object result = pjp.proceed();
System.out.println("Advice 2 after");
return result;
}
执行顺序是:
Advice 1 before
Advice 2 before
--- 调用目标方法 ---
Advice 2 after
Advice 1 after
✅ 小结:Spring AOP 中 @Around 执行流程
- Spring 使用动态代理或 CGLIB 生成代理类
- 拦截所有目标方法,通过
MethodInterceptor组成一个拦截链 @Around被包装成MethodInterceptor,按顺序组成调用链ProceedingJoinPoint实际由MethodInvocation对象实现proceed()会继续调用下一个拦截器,最后执行目标方法

被折叠的 条评论
为什么被折叠?



