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

1113

积分

0

好友

163

主题
发表于 3 天前 | 查看: 8| 回复: 0

一、从ProxyFactory说起:代理对象的创建入口

Spring AOP的代理对象创建入口是ProxyFactory,它是Spring提供的一个简化AOP配置的工具类。我们先看ProxyFactory的核心方法:

// ProxyFactory.java
public class ProxyFactory extends ProxyCreatorSupport {
    public Object getProxy() {
        return createAopProxy().getProxy();
    }
    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        return getAopProxyFactory().createAopProxy(this);
    }
}

getProxy()方法是创建代理对象的入口,它调用createAopProxy()生成AopProxy实例,再通过AopProxygetProxy()方法生成最终的代理对象。

二、AdvisedSupport:AOP配置的“中枢神经”

AdvisedSupportProxyFactory的父类,负责管理AOP的核心配置(目标对象、通知、拦截器等)。其中最关键的是getInterceptorsAndDynamicInterceptionAdvice方法,它负责构建拦截链:

// AdvisedSupport.java
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
    MethodCacheKey key = new MethodCacheKey(method);
    List<Object> cached = this.methodCache.get(key);
    if (cached == null) {
        cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
                this, method, targetClass);
        this.methodCache.put(key, cached);
    }
    return cached;
}

这个方法会根据目标方法和类,从advisorChainFactory获取拦截器链,并缓存起来,避免重复计算。

三、JdkDynamicAopProxy:JDK动态代理的实现核心

如果目标对象实现了接口,Spring会使用JdkDynamicAopProxy生成代理对象。它的invoke方法是代理执行的核心

// JdkDynamicAopProxy.java
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    TargetSource targetSource = this.advised.targetSource;
    Object target = null;
    try {
        // 1. 获取拦截器链
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
        // 2. 无拦截器则直接调用目标方法
        if (chain.isEmpty()) {
            return AopUtils.invokeJoinpointUsingReflection(target, method, args);
        }
        // 3. 创建MethodInvocation执行拦截链
        MethodInvocation invocation = new ReflectiveMethodInvocation(
                proxy, target, method, args, targetClass, chain);
        return invocation.proceed();
    } finally {
        targetSource.releaseTarget(target);
    }
}

invoke方法的核心逻辑是:获取拦截链→创建MethodInvocation→执行拦截链。

四、MethodInterceptor:拦截逻辑的执行引擎

MethodInterceptorSpring AOP的核心接口,所有的拦截逻辑都集中在intercept方法中。我们看一个简化的实现:

// 自定义MethodInterceptor
public class MyInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(MethodInvocation invocation) throws Throwable {
        // 1. 前置处理:记录日志
        System.out.println("执行方法:" + invocation.getMethod().getName());
        try {
            // 2. 调用目标方法(触发下一个拦截器)
            Object result = invocation.proceed();
            // 3. 后置处理:统计执行时间
            System.out.println("方法执行耗时:" + calculateTime());
            return result;
        } catch (Exception e) {
            // 4. 异常处理:上报错误
            System.out.println("方法执行异常:" + e.getMessage());
            throw e;
        }
    }
}

intercept方法的核心是invocation.proceed(),它会触发下一个拦截器的执行,直到所有拦截器执行完毕,再调用目标方法。

五、拦截链的执行流程:从proceed到invokeTargetMethod

我们通过UML时序图更直观地看拦截链的执行流程:

alt

ReflectiveMethodInvocationproceed方法是拦截链执行的关键:

// ReflectiveMethodInvocation.java
@Override
public Object proceed() throws Throwable {
    // 1. 所有拦截器执行完毕,调用目标方法
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return invokeJoinpoint();
    }
    // 2. 获取下一个拦截器
    Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(
            ++this.currentInterceptorIndex);
    // 3. 执行拦截器的intercept方法
    if (interceptorOrInterceptionAdvice instanceof MethodInterceptor) {
        MethodInterceptor mi = (MethodInterceptor) interceptorOrInterceptionAdvice;
        return mi.intercept(this);
    } else {
        // 处理其他类型的通知(如BeforeAdvice)
        return ((Interceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

proceed方法会循环执行拦截链中的每个MethodInterceptor,直到所有拦截器执行完毕,再调用invokeJoinpoint()执行目标方法。





上一篇:ECM模式USB网卡驱动实战:基于CH397A的描述符解析与数据传输
下一篇:现代化串口调试工具comNG:开源免费、支持数据可视化与二次开发
您需要登录后才可以回帖 登录 | 立即注册

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

GMT+8, 2025-12-17 16:31 , Processed in 0.138789 second(s), 37 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

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