你有没有想过,@Before、@After这些Advice注解为什么能“精准插入”到目标方法里?为什么配置一个@Aspect就能让逻辑“自动生效”?这背后是Spring将Advice包装成拦截器、再通过代理串起整个执行链的底层逻辑。本文从源码出发,为你揭示其完整的执行链路。
一、Advice的核心:从“配置”到“拦截器”的转化
Spring AOP的核心在于把Advice(通知)转化为MethodInterceptor(方法拦截器),再通过代理对象将拦截器链插入目标方法的执行流程中。我们通常从ProxyFactory开始分析——它是Spring创建AOP代理的核心入口。
1. ProxyFactory的核心逻辑:组装Advice与Pointcut
当我们配置ProxyFactory时,本质是将Advice和Pointcut(切点)绑定成Advisor(通知器)。其简化后的核心代码如下:
// ProxyFactory.java
public class ProxyFactory extends ProxyCreatorSupport {
public ProxyFactory(Object target, Advisor... advisors) {
setTarget(target);
addAdvisors(advisors); // 将Advice包装成Advisor
}
public Object getProxy() {
return createAopProxy().getProxy(); // 生成代理对象
}
}
此处的关键在于createAopProxy()方法——它会根据目标类是否实现接口,选择使用JdkDynamicAopProxy(JDK动态代理)或CglibAopProxy(CGLIB代理)。然而更核心的步骤是拦截器链的生成,这由DefaultAdvisorChainFactory完成。
2. DefaultAdvisorChainFactory:生成拦截器链的核心
DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法,是将Advisor转化为MethodInterceptor的关键。简化代码如下:
// DefaultAdvisorChainFactory.java
public class DefaultAdvisorChainFactory implements AdvisorChainFactory {
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class<?> targetClass) {
// 1. 获取AdvisorAdapterRegistry(用于适配Advice)
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 2. 获取所有Advisor
Advisor[] advisors = config.getAdvisors();
List<Object> interceptors = new ArrayList<>();
for (Advisor advisor : advisors) {
if (advisor instanceof PointcutAdvisor) {
// 3. 检查Pointcut是否匹配当前方法
if (((PointcutAdvisor) advisor).getPointcut().getMethodMatcher().matches(method, targetClass)) {
// 4. 将Advisor转化为Interceptor
interceptors.addAll(registry.getInterceptors(advisor));
}
}
}
return interceptors;
}
}
这段代码的核心在于registry.getInterceptors(advisor)调用——它通过AdvisorAdapterRegistry把Advice适配成MethodInterceptor,这是Java框架中处理横切关注点的精巧设计。
3. AdvisorAdapter:Advice到Interceptor的“翻译官”
AdvisorAdapterRegistry是一个注册中心,内部维护了AdvisorAdapter(适配器)列表。例如,MethodBeforeAdviceAdapter负责将MethodBeforeAdvice转化为MethodInterceptor,其简化代码如下:
// MethodBeforeAdviceAdapter.java
public class MethodBeforeAdviceAdapter implements AdvisorAdapter {
@Override
public boolean supportsAdvice(Advice advice) {
return advice instanceof MethodBeforeAdvice;
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
// 返回MethodBeforeAdviceInterceptor,包装原始Advice
return new MethodBeforeAdviceInterceptor(advice);
}
}
这里的MethodBeforeAdviceInterceptor是真正的拦截器,它的invoke方法会在目标方法执行前调用MethodBeforeAdvice的before方法,实现了前置通知的逻辑:
// MethodBeforeAdviceInterceptor.java
public class MethodBeforeAdviceInterceptor implements MethodInterceptor {
private final MethodBeforeAdvice advice;
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); // 执行@Before逻辑
return mi.proceed(); // 执行目标方法
}
}
至此,@Before注解的底层逻辑已然清晰:通过特定的Adapter把Advice包装成标准的Interceptor,再由这个Interceptor在代理链中插入到目标方法的执行流程之前。
二、核心流程可视化:UML时序图
为了更直观地展示从配置到拦截器生成的完整流程,我们绘制了如下UML时序图:

三、从拦截器到代理:最终的“逻辑插入”
当拦截器链生成后,ProxyFactory会调用createAopProxy()生成最终的代理对象。
以JdkDynamicAopProxy为例,其invoke方法会遍历并执行拦截器链:
// JdkDynamicAopProxy.java
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 1. 获取拦截器链
List<Object> interceptors = chainFactory.getInterceptorsAndDynamicInterceptionAdvice(...);
// 2. 生成MethodInvocation(方法调用器)
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, interceptors);
// 3. 执行拦截器链
return invocation.proceed();
}
ReflectiveMethodInvocation的proceed方法是整个拦截器链得以顺序执行的核心,其实现体现了经典的责任链模式:
// ReflectiveMethodInvocation.java
@Override
public Object proceed() throws Throwable {
// 1. 如果没有更多拦截器,执行目标方法
if (this.currentInterceptorIndex == this.interceptors.size() - 1) {
return invokeJoinpoint();
}
// 2. 获取下一个拦截器
Object interceptorOrInterceptionAdvice = this.interceptors.get(++this.currentInterceptorIndex);
// 3. 执行拦截器逻辑
if (interceptorOrInterceptionAdvice instanceof MethodInterceptor) {
MethodInterceptor mi = (MethodInterceptor) interceptorOrInterceptionAdvice;
return mi.invoke(this);
}
// 4. 否则继续递归
return proceed();
}
这段代码的逻辑是:每个拦截器执行完自身的逻辑后,通过调用proceed()将控制权传递给链中的下一个拦截器,直到所有拦截器执行完毕,最终才执行原始的目标方法。
四、总结:Advice的本质是“拦截器链”
通过以上源码分析,Spring Advice的底层执行逻辑已经非常清晰:
- 配置阶段:将
Advice和Pointcut绑定成Advisor。
- 适配阶段:通过
AdvisorAdapter将不同类型的Advice转化为统一的MethodInterceptor。
- 代理阶段:根据目标对象选择合适的代理技术(JDK或CGLIB)生成代理对象,并将拦截器链与代理对象关联。
- 执行阶段:通过
ReflectiveMethodInvocation遍历并执行拦截器链,完成切面逻辑的插入。
无论是使用@Aspect注解还是传统的XML配置,其本质都是在遵循这套流程。Spring框架的巧妙之处在于,它将这套复杂的代理与拦截机制封装成简单易用的声明式编程模型。理解了这个从“通知”到“拦截器链”的转化过程,对于解决AOP实践中的拦截顺序、代理方式选择等问题大有裨益。