盘点 AOP : AOP 的拦截对象的创建

首先分享之前的所有文章 , 欢迎点赞收藏转发三连下次一定 >>>> ???
文章合集 : ? juejin.cn/post/694164…
Github : ? github.com/black-ant

一 . 前言

之前说了 AOP初始化AOP 代理类的创建 , 这一篇来看一下 AOP 拦截对象的创建

二 . CglibAopProxy 代理模块

AOP 的主要代理类还是 CglibAopProxy , 所以整体流程还是以该对象为例 :

2.1 拦截对象创建的入口

在 CglibAopProxy # getProxy 主流程中 , 有几个比较重要的逻辑 , 把这几个流程整合后看一下 :

// 代码做过一定程度的省略和魔改
public Object getProxy(@Nullable ClassLoader classLoader) {

    //... 省略主要逻辑
    Enhancer enhancer = createEnhancer();
    
    // rootClass => com.gang.aop.demo.service.StartService
    // 获取所有的回调对象 -> PIC21001 :  Callback[] 系列参数
    Callback[] callbacks = getCallbacks(rootClass);
    Class<?>[] types = new Class<?>[callbacks.length];
    for (int x = 0; x < types.length; x++) {
        types[x] = callbacks[x].getClass();
    }

    enhancer.setCallbackFilter(new ProxyCallbackFilter(
        this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, 
        this.fixedInterceptorOffset));
    enhancer.setCallbackTypes(types);

    // Generate the proxy class and create a proxy instance.
    // return createProxyClassAndInstance(enhancer, callbacks);
    enhancer.setInterceptDuringConstruction(false);
    enhancer.setCallbacks(callbacks);
    return (this.constructorArgs != null && this.constructorArgTypes != null ?
        enhancer.create(this.constructorArgTypes, this.constructorArgs) :
        enhancer.create());
}

复制代码

PIC21001 : Callback[] 系列参数

image.png

2.1.1 创建 Callback 对象

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
        // 是否为每次调用公开AOP代理
        boolean exposeProxy = this.advised.isExposeProxy();
        // 配置是否被冻结,并且不能进行通知更改
        boolean isFrozen = this.advised.isFrozen();
        // 是否所有对#getTarget()的调用都返回同一个对象
        boolean isStatic = this.advised.getTargetSource().isStatic();

        // 选择一个 AOP 拦截器 -> 此处创建的是 DynamicAdvisedInterceptor , 这是一个重要的类 -> 2.1.2
        // advised -> PIC21101 
        Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

        // 选择性创建 StaticUnadvisedInterceptor / DynamicUnadvisedInterceptor
        Callback targetInterceptor;
        if (exposeProxy) {
            targetInterceptor = (isStatic ?
                    new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
                    new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
        }
        else {
            targetInterceptor = (isStatic ?
                    new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
                    new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
        }

        // 选择一个目标分派器
        // StaticDispatcher : 静态目标的调度器 , Dispatcher比Interceptor快得多
        Callback targetDispatcher = (isStatic ?
                new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
        
        // PICPIC21102
        Callback[] mainCallbacks = new Callback[] {
                aopInterceptor,  // for normal advice
                targetInterceptor,  // invoke target without considering advice, if optimized
                new SerializableNoOp(),  // no override for methods mapped to this
                targetDispatcher, this.advisedDispatcher,
                new EqualsInterceptor(this.advised),
                new HashCodeInterceptor(this.advised)
        };

        Callback[] callbacks;

        // 如果目标是静态的,并且通知链是冻结的,那么我们可以通过使用该方法的固定链将AOP调用直接发送到目标
        if (isStatic && isFrozen) {
            Method[] methods = rootClass.getMethods();
            Callback[] fixedCallbacks = new Callback[methods.length];
            this.fixedInterceptorMap = new HashMap<>(methods.length);

            for (int x = 0; x < methods.length; x++) {
                Method method = methods[x];
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
                fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
                        chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
                this.fixedInterceptorMap.put(method, x);
            }

            // 从mainCallbacks和fixedCallbacks复制回调函数到callbacks数组中
            callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
            System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
            System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
            this.fixedInterceptorOffset = mainCallbacks.length;
        }
        else {
            callbacks = mainCallbacks;
        }
        // 返回所有的回调对象
        return callbacks;
    }
复制代码

PIC21101 advised 中已经包含目标对象和通知面

image.png

PIC21102 : mainCallbacks 结构

image.png

扩展 : ProxyCallbackFilter 的作用

作用: CallbackFilter为方法分配回调
介绍: 该类实现了一个 Accept 方法 , 用于返回回调函数的索引

private static class ProxyCallbackFilter implements CallbackFilter {

    private final AdvisedSupport advised;

    private final Map<Method, Integer> fixedInterceptorMap;

    private final int fixedInterceptorOffset;
    
}
复制代码

2.1.2 DynamicAdvisedInterceptor

作用 : 当目标是动态的或代理未被冻结时使用 , 会使用该通用的AOP回调
发起 : 从 2.1.1 中 getCallbacks 中可以看到创建流程

// 那么来看一下这个对象是如何实现方法的拦截的
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

    // PRO212001 : AdvisedSupport 的作用
    private final AdvisedSupport advised;

    public DynamicAdvisedInterceptor(AdvisedSupport advised) {
        this.advised = advised;
    }

    @Override
    @Nullable
    // proxy -> EnhancerBySpringCGLIB 代理
    // method -> 实际业务方法
    // args : 方法参数
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;
        Object target = null;
        // 当前调用的目标 ,
        TargetSource targetSource = this.advised.getTargetSource();
        try {
            if (this.advised.exposeProxy) {
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }
            // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
            target = targetSource.getTarget();
            Class<?> targetClass = (target != null ? target.getClass() : null);
            // 根据此配置确定给定方法的MethodInterceptor对象列表
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            Object retVal;
            // 检查我们是否只有一个InvokerInterceptor (没有通知 , 只有反射调用)
            if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
               // 方法代理直接调用
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = methodProxy.invoke(target, argsToUse);
            }
            else {
                // 核心逻辑 , 此处创建了一个方法调用
                retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
            }
            // 处理返回类型
            retVal = processReturnType(proxy, target, method, retVal);
            return retVal;
        }
        finally {
            if (target != null && !targetSource.isStatic()) {
                targetSource.releaseTarget(target);
            }
            if (setProxyContext) {
                // 恢复旧的代理
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }
}



// SingletonTargetSource 对象结构
public class SingletonTargetSource implements TargetSource, Serializable {

    // 使用反射缓存和调用的目标
    private final Object target;
}

// CglibMethodInvocation 结构
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {

    @Nullable
    private final MethodProxy methodProxy;

    public CglibMethodInvocation(Object proxy, @Nullable Object target, Method method,
        Object[] arguments, @Nullable Class<?> targetClass,
        List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {

        super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);

    // 仅对非java.lang.Object派生的公共方法使用方法代理
    this.methodProxy = (Modifier.isPublic(method.getModifiers()) &&
    method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
        !AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?
        methodProxy : null);
}

    

复制代码

可以看到 , DynamicAdvisedInterceptor 是 MethodInterceptor 的实现类 , 该接口对方法进行拦截

MethodInterceptor 的继承体系 :
Systerm-DynamicAdvisedInterceptor.png

PRO212001 : AdvisedSupport 的作用

作用 : AOP代理配置管理器的基类。其本身不是AOP代理,但是该类的子类通常是工厂,从这些工厂中直接获得AOP代理实例

特点 : 这个类是可序列化的 , 用于保存代理的快


public class AdvisedSupport extends ProxyConfig implements Advised {

    // 通知链工厂 -> Pro
    AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();

    // key 为方法缓存 , value 为 advisor 链
    private transient Map<MethodCacheKey, List<Object>> methodCache;

    // 代理要实现的接口
    private List<Class<?>> interfaces = new ArrayList<>();

    // Advisor 对象集合 , 每一个通知会包装为通知者放在该集合中
    private List<Advisor> advisors = new ArrayList<>();

    // 用于内部操作 , advisor 改变后会刷新该对象
    private Advisor[] advisorArray = new Advisor[0];

}

// AdvisorChainFactory 的作用

复制代码

System-AdvisedSupport.png

代理的核心逻辑 :

对应的方法已经在前面通过 Enhancer 进行 CGLIB 代理了 , 调用时实际调用的是 DynamicAdvisedInterceptor , 再由 DynamicAdvisedInterceptor 完成 AOP 类的调用

PS : 这里涉及到动态代理的相关概念 ,会生成 xxx$$EnhancerBySpringCGLIB$$… 的实际类 , 进行 Class 层面的调用 , 这些后面单独说说

总结

请求方DynamicAdvisedInterceptorCglibMethodInvocation切面请求方调用 Interceptor 对象调用 CglibMethodInvocation 发起切面的调用实际调用到切面对象 , 执行对应的通知方法请求方DynamicAdvisedInterceptorCglibMethodInvocation切面

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享