找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1709

积分

1

好友

242

主题
发表于 2025-12-14 16:08:42 | 查看: 29| 回复: 0

你有没有想过,@Before@After这些Advice注解为什么能“精准插入”到目标方法里?为什么配置一个@Aspect就能让逻辑“自动生效”?这背后是Spring将Advice包装成拦截器、再通过代理串起整个执行链的底层逻辑。本文从源码出发,为你揭示其完整的执行链路。

一、Advice的核心:从“配置”到“拦截器”的转化

Spring AOP的核心在于把Advice(通知)转化为MethodInterceptor(方法拦截器),再通过代理对象将拦截器链插入目标方法的执行流程中。我们通常从ProxyFactory开始分析——它是Spring创建AOP代理的核心入口。

1. ProxyFactory的核心逻辑:组装Advice与Pointcut

当我们配置ProxyFactory时,本质是将AdvicePointcut(切点)绑定成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:生成拦截器链的核心

DefaultAdvisorChainFactorygetInterceptorsAndDynamicInterceptionAdvice方法,是将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)调用——它通过AdvisorAdapterRegistryAdvice适配成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方法会在目标方法执行前调用MethodBeforeAdvicebefore方法,实现了前置通知的逻辑:

// 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时序图:

Advice执行链路时序图

三、从拦截器到代理:最终的“逻辑插入”

当拦截器链生成后,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();
}

ReflectiveMethodInvocationproceed方法是整个拦截器链得以顺序执行的核心,其实现体现了经典的责任链模式

// 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的底层执行逻辑已经非常清晰:

  1. 配置阶段:将AdvicePointcut绑定成Advisor
  2. 适配阶段:通过AdvisorAdapter将不同类型的Advice转化为统一的MethodInterceptor
  3. 代理阶段:根据目标对象选择合适的代理技术(JDK或CGLIB)生成代理对象,并将拦截器链与代理对象关联。
  4. 执行阶段:通过ReflectiveMethodInvocation遍历并执行拦截器链,完成切面逻辑的插入。

无论是使用@Aspect注解还是传统的XML配置,其本质都是在遵循这套流程。Spring框架的巧妙之处在于,它将这套复杂的代理与拦截机制封装成简单易用的声明式编程模型。理解了这个从“通知”到“拦截器链”的转化过程,对于解决AOP实践中的拦截顺序、代理方式选择等问题大有裨益。




上一篇:USearch高性能向量检索引擎解析:轻量级ANN库在AI与RAG场景下的应用
下一篇:嵌入式C语言面试题精选:10大必考知识点与实战代码解析
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-24 21:10 , Processed in 0.298893 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表