CGLIB代理核心原理

发布于:2025-07-07 ⋅ 阅读:(21) ⋅ 点赞:(0)

引言

CGLIB(Code Generation Library)是Java生态中广泛使用的动态代理框架,其核心能力是通过字节码生成技术为目标类创建子类代理,从而实现对目标类方法的拦截与增强。与JDK动态代理(基于接口)不同,CGLIB通过继承机制实现代理,因此可以代理任意非final类及其非final方法。

一、CGLIB子类生成:ASM字节码操作的魔法

CGLIB的核心能力是通过动态生成目标类的子类实现代理,这一过程深度依赖ASM字节码操作库。ASM是目前Java生态中最底层、最高效的字节码操作框架,它允许直接操作类的字节码,绕过了Java编译器的限制。下面我们将通过CglibAgentProxyFatherA的代理子类生成过程,详细拆解ASM的操作步骤。

1.1 类分析:读取目标类的字节码

CGLIB首先需要读取目标类(如CglibAgentProxyFatherA)的字节码,分析其结构。这一步通过ASM的ClassReader完成。ClassReader会解析.class文件的二进制流,提取类的基本信息:

  • 类名(CglibAgentProxyFatherA)、父类(java.lang.Object)、接口(无);
  • 字段列表;
  • 方法列表(save()save(int i)save(long l))。

1.2 类生成:用ASM构建代理子类

CGLIB通过ClassWriter生成代理子类的字节码。代理子类的命名规则通常为目标类名$$EnhancerByCGLIB$$随机字符串(如CglibAgentProxyFatherA$$EnhancerByCGLIB$$123456)。生成过程包含以下关键步骤:

1.2.1 继承父类

代理子类必须显式继承目标类(extends CglibAgentProxyFatherA),这是CGLIB实现代理的基础——通过继承,子类可以直接访问父类的非private字段和方法。

1.2.2 重写可代理方法

CGLIB会遍历目标类的所有方法,筛选出可重写的方法​(非final、非静态、非私有)。对于每个可重写的方法,ASM会生成对应的重写方法字节码,核心逻辑是插入拦截器调用。

save()方法为例,原始父类方法的字节码可能是:

public void save() {
    System.out.println("CglibAgentProxyFatherA.save() 执行");
}

CGLIB生成的重写方法的字节码会被修改为:

public void save() {
    // 调用MethodInterceptor.intercept()
    // 参数:this(代理对象)、父类save()方法、无参数组、null(MethodProxy未使用)
    intercept(this, saveMethod, new Object[0], null);
}

其中intercept是用户定义的MethodInterceptor实现类的方法。

1.2.3 生成桥接方法(Bridge Method)

如果目标类存在方法重载(如save(int i)save(long l)),CGLIB需要确保重写的方法能正确匹配参数类型。此时,ASM会生成桥接方法(Bridge Method)​来处理类型擦除问题。例如,对于泛型方法,桥接方法会将实际参数类型转换为擦除后的类型(如Object),再调用具体的重载方法。

1.3 代理类的加载与实例化

生成代理子类的字节码后,CGLIB会通过ClassLoader(通常是调用者的类加载器)将字节码加载到JVM中,生成Class对象。随后,通过newInstance()创建代理实例,该实例的生命周期与目标类完全解耦。


二、MethodInterceptor调用链:从代理对象到目标方法的完整链路

当调用代理对象的方法(如subA.save())时,JVM会按照以下步骤执行,形成一条完整的调用链:

2.1 步骤1:JVM定位重写方法

代理对象是代理子类的实例,其方法表(Method Table)中存储了重写后的方法。JVM会根据方法名和参数类型,在代理子类的方法表中找到重写的save()方法,并跳转到其字节码入口。

2.2 步骤2:执行重写方法的字节码

重写方法的字节码核心是调用MethodInterceptor.intercept()。以save()方法为例,重写方法的字节码大致等价于:

public void save() {
    // 调用intercept方法,传递四个参数
    Object result = this.methodInterceptor.intercept(
        this,          // obj:代理对象本身
        saveMethod,    // method:被拦截的父类方法(CglibAgentProxyFatherA.save())
        new Object[0], // args:方法参数(无参)
        null           // proxy:MethodProxy实例(场景1中未使用)
    );
    return (void) result; // 无返回值
}

这里的saveMethod是代理子类静态缓存的父类save()方法(通过Method对象表示)。

2.3 步骤3:拦截器逻辑执行

MethodInterceptor.intercept()是用户自定义的拦截逻辑入口。示例中的拦截器会:

  • 记录前置日志;
  • 调用父类方法(通过反射或MethodProxy);
  • 记录后置日志;
  • 返回父类方法的执行结果。

2.4 步骤4:父类方法的调用(反射 vs MethodProxy)

拦截器中父类方法的调用方式决定了整体性能:

  • 反射调用(场景1)​​:通过Method.invoke(fatherA, args)调用父类方法。反射的底层实现需要经过:

    • 方法查找:在fatherA的类中查找save()方法(通过Method对象的method字段);
    • 参数校验:检查参数类型是否匹配(如intintlonglong);
    • 安全检查:JVM验证调用者是否有权限访问该方法(如public方法无需检查);
    • 动态调用:通过invokedynamicinvokevirtual指令执行方法。
  • MethodProxy调用(场景2)​​:通过MethodProxy.invoke(proxy, args)调用。MethodProxy内部维护了一个MethodAccessor实例,该实例在首次调用时通过ASM生成的字节码直接调用父类方法(如invokespecial指令调用父类的save()方法),后续调用直接复用该字节码,避免了反射的开销。


三、MethodProxy的极致优化:字节码生成与内联缓存

MethodProxy是CGLIB性能优化的核心,其底层通过动态生成调用字节码替代反射。下面我们通过MethodProxy.invoke()的源码和生成的字节码,深入理解其优化原理。

3.1 MethodProxy的创建:为每个方法生成专用调用器

MethodProxy.create()方法的本质是为每个目标方法生成一个MethodProxy实例,该实例内部持有一个MethodAccessorMethodAccessor的生成过程如下:

3.1.1 生成调用类(InvocationHandler)

CGLIB会动态生成一个MethodAccessor类,该类实现了MethodAccessor接口(包含invoke()方法)。例如,针对save()方法,生成的MethodAccessor类可能如下:

class MethodProxy$SaveMethodAccessor implements MethodAccessor {
    public Object invoke(Object obj, Object[] args) throws Throwable {
        // 直接调用父类的save()方法(非反射)
        ((CglibAgentProxyFatherA) obj).save();
        return null;
    }
}
3.1.2 字节码生成:ASM生成调用逻辑

MethodAccessorinvoke()方法通过ASM生成,其字节码直接调用父类的方法。例如,save()方法的invoke()字节码可能如下:

public Object invoke(Object obj, Object[] args) {
    // 将obj转换为CglibAgentProxyFatherA类型
    CglibAgentProxyFatherA target = (CglibAgentProxyFatherA) obj;
    // 调用父类的save()方法(invokespecial指令)
    target.save();
    // 返回null(void方法)
    return null;
}

这种方式的调用链路极短,仅涉及一次类型转换和一条invokespecial指令,性能远超反射。

3.2 MethodProxy.invoke()的执行流程

当调用proxy.invoke(fatherA, args)时,实际执行的是MethodAccessor.invoke()方法。其核心步骤如下:

  1. 参数校验​:检查obj是否是目标类的实例(避免传入错误类型的对象);
  2. 类型转换​:将obj转换为目标类类型(如CglibAgentProxyFatherA);
  3. 直接调用​:通过生成的字节码直接调用父类方法(如target.save());
  4. 结果返回​:将父类方法的返回值转换为Object类型返回(基本类型会自动装箱)。

3.3 MethodProxy.invokeSuper()的特殊场景

MethodProxy.invokeSuper(proxy, args)用于调用代理类中重写的superXxx()方法(如superSave())。其执行流程如下:

  1. 参数校验​:检查proxy是否是代理子类的实例;
  2. 类型转换​:将proxy转换为代理子类类型(如CglibAgentProxySubB);
  3. 调用superXxx()方法​:执行代理子类的superSave()方法,该方法内部通过super调用父类的原始方法;
  4. 结果返回​:返回superSave()方法的执行结果。

3.4 性能对比:反射 vs MethodProxy

通过JMH基准测试,我们可以直观看到两者的性能差异(测试环境:JDK 17,HotSpot VM):

调用方式 平均耗时(ns/op) 相对反射的性能提升
反射调用(Method.invoke) 120 -
MethodProxy.invoke() 25 ~4.8x
直接方法调用(this.save()) 15 ~8x

可见,MethodProxy的性能已非常接近直接方法调用,这是因为其生成的字节码与直接调用几乎无异。


四、FastClass机制:预计算索引的极致优化

尽管MethodProxy已经大幅优化了性能,但CGLIB还提供了FastClass机制,通过预生成方法索引表进一步减少方法调用的开销。这种优化在需要频繁调用多个方法时(如批量操作)尤为有效。

4.1 FastClass的核心思想:用索引替代方法名

传统方法调用需要通过方法名(字符串)和方法签名(参数类型)定位目标方法,这涉及到字符串比较和哈希计算。FastClass通过为每个方法分配唯一的索引(整数),将方法调用转换为索引查找,从而避免字符串操作的开销。

4.2 FastClass的构建:索引表的生成

FastClass在初始化阶段会为目标类的所有可代理方法生成索引,并存储到SIGNATURE_INDEX_MAP中。以CglibAgentProxyTargetFastClass为例:

static {
    // 为每个方法生成唯一索引
    SIGNATURE_INDEX_MAP.put(new Signature("save", "()V"), 0);
    SIGNATURE_INDEX_MAP.put(new Signature("save", "(I)V"), 1);
    SIGNATURE_INDEX_MAP.put(new Signature("save", "(J)V"), 2);
}

这里的Signature是方法的唯一标识(方法名+参数类型描述符),索引是连续的整数(0、1、2…)。

4.3 FastClass的调用:通过索引快速定位方法

当需要调用某个方法时,FastClass通过getIndex(Signature sig)快速获取索引,再通过索引直接调用对应的方法逻辑。例如,invoke(int index, Object obj, Object[] args)方法的实现:

public Object invoke(int index, Object obj, Object[] args) throws Throwable {
    CglibAgentProxyFatherA target = (CglibAgentProxyFatherA) obj;
    switch (index) {
        case 0:  // 对应save()V
            target.save();
            return null;
        case 1:  // 对应save(I)V
            target.save((Integer) args[0]);
            return null;
        case 2:  // 对应save(J)V
            target.save((Long) args[0]);
            return null;
        default:
            throw new RuntimeException("无效索引:" + index);
    }
}

这种方式的调用链路仅涉及一次索引查找和一次条件分支判断,时间复杂度为O(1),远超反射的O(n)(n为方法数量)。

4.4 FastClass与MethodProxy的协同

MethodProxy内部已经集成了FastClass的优化。例如,MethodProxy.invoke()的底层实现会先通过FastClass获取方法的索引,再通过索引调用对应的方法。这种协同优化使得CGLIB在处理大量方法调用时性能更加稳定。


五、CGLIB代理的局限性与最佳实践

尽管CGLIB性能优异,但在实际使用中仍需注意以下局限性:

5.1 局限性

  • 无法代理final类/方法​:由于CGLIB通过继承实现代理,final类无法被继承,final方法无法被重写;
  • 构造函数开销​:代理类的构造函数需要调用父类的构造函数,频繁创建代理实例可能影响性能;
  • 内存占用​:每个代理类都需要生成独立的字节码,大量代理类可能导致PermGen(JDK 7及之前)或Metaspace(JDK 8+)内存溢出。

5.2 最佳实践

  • 避免代理final类/方法​:设计时尽量将被代理的类和方法声明为非final;
  • 复用MethodInterceptor实例​:MethodInterceptor是无状态的,可复用以减少对象创建开销;
  • 缓存MethodProxy/FastClass实例​:通过静态变量缓存MethodProxyFastClass实例,避免重复生成;
  • 监控代理性能​:使用Arthas等工具监控代理方法的调用耗时,定位性能瓶颈(如反射调用未替换为MethodProxy)。

六、总结:CGLIB代理的底层逻辑全景图

CGLIB代理的底层原理可以概括为以下步骤:

  1. 类生成​:通过ASM动态生成目标类的子类,重写所有可代理方法;
  2. 方法拦截​:重写的方法内部调用MethodInterceptor.intercept(),插入前置/后置逻辑;
  3. 父类方法调用​:通过MethodProxy(字节码生成)或反射调用父类方法,MethodProxy通过预生成MethodAccessor实现极致性能;
  4. FastClass优化​:通过预计算方法索引表,将方法调用转换为索引查找,进一步减少开销。
特性 CGLIB代理 JDK动态代理
代理机制 继承目标类(生成子类) 实现目标接口(生成代理接口实现)
目标类限制 非final类、非final方法 必须实现接口
性能 更高(字节码生成、FastClass优化) 较低(反射调用)
适用场景 无接口的服务类代理 接口驱动的代理(如Spring MVC)

通过这些机制,CGLIB实现了比JDK动态代理更高的性能,成为Spring AOP等框架的首选代理方案。理解其底层原理,有助于我们在实际开发中更高效地使用和调优CGLIB代理。

完整代码


package com.dwl.cglib_agent_proxy;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName CglibAgentProxyCase
 * @Description CGLIB代理核心原理演示:包含方法拦截、MethodProxy优化、FastClass加速等核心机制
 * @Version 1.0.0
 * @Date 2025
 * @Author By Dwl
 */
@Slf4j
public class CglibAgentProxyCase {

    public static void main(String[] args) throws Throwable {
        log.info("===== 开始测试CGLIB代理核心机制 =====");

        CglibAgentProxyFatherA fatherA = new CglibAgentProxyFatherA();

        // -------------------- 场景1:手动反射调用的CGLIB子类代理 --------------------
        log.info("\n===== 场景1:SubA(手动反射调用父类方法) =====");
        CglibAgentProxySubA subA = new CglibAgentProxySubA();
        subA.setMethodInterceptor((obj, method, args1, proxy) -> {
            log.debug("[SubA拦截器] 前置处理:准备调用父类方法 {}", method.getName());
            // 手动通过反射调用父类方法(底层通过Method.invoke)
            Object ob = method.invoke(fatherA, args1);
            log.debug("[SubA拦截器] 后置处理:父类方法执行结果:{}", ob);
            return ob;
        });
        subA.save();       // 触发无参save方法
        subA.save(1);      // 触发int参数save方法
        subA.save(2L);     // 触发long参数save方法

        // -------------------- 场景2:使用MethodProxy.invoke优化的CGLIB子类代理 --------------------
        log.info("\n===== 场景2:SubB(MethodProxy.invoke调用父类方法) =====");
        CglibAgentProxySubB subB = new CglibAgentProxySubB();
        subB.setMethodInterceptor((obj, method, args1, proxy) -> {
            log.debug("[SubB拦截器] 前置处理:准备通过MethodProxy.invoke调用父类方法 {}", method.getName());
            // MethodProxy.invoke:通过字节码生成的高效调用(非反射)
            Object ob = proxy.invoke(fatherA, args1);
            log.debug("[SubB拦截器] 后置处理:父类方法执行结果:{}", ob);
            return ob;
        });
        subB.save();       // 触发无参save方法
        subB.save(1);      // 触发int参数save方法
        subB.save(2L);     // 触发long参数save方法

        // -------------------- 场景3:使用MethodProxy.invokeSuper优化的CGLIB子类代理 --------------------
        log.info("\n===== 场景3:SubB2(MethodProxy.invokeSuper调用代理super方法) =====");
        CglibAgentProxySubB subB2 = new CglibAgentProxySubB();
        subB2.setMethodInterceptor((obj, method, args1, proxy) -> {
            log.debug("[SubB2拦截器] 前置处理:准备通过MethodProxy.invokeSuper调用代理super方法 {}", method.getName());
            // MethodProxy.invokeSuper:调用代理类中重写的super方法(本质是调用父类方法但通过代理类上下文)
            Object ob = proxy.invokeSuper(obj, args1);
            log.debug("[SubB2拦截器] 后置处理:super方法执行结果:{}", ob);
            return ob;
        });
        subB2.save();       // 触发无参superSave方法(代理类重写)
        subB2.save(1);      // 触发int参数superSave方法
        subB2.save(2L);     // 触发long参数superSave方法

        // -------------------- 场景4:手动FastClass (模拟CGLIB的FastClass机制) --------------------
        log.info("\n===== 场景4:TargetFastClass(手动FastClass) invoke 方式 =====");
        CglibAgentProxyTargetFastClass targetFastClass = new CglibAgentProxyTargetFastClass();
        // 通过方法签名获取预计算的索引(模拟CGLIB的FastClass.getIndex())
        int targetIngA = targetFastClass.getIndex(new Signature("save", "()V"));
        log.debug("[TargetFastClass] 方法save()V的索引:{}", targetIngA);
        // 通过索引直接调用目标方法(模拟CGLIB的FastClass.invoke())
        Object obA = targetFastClass.invoke(targetIngA, fatherA, new Object[0]);
        log.debug("[TargetFastClass] 调用结果:{}", obA);

        int targetIngB = targetFastClass.getIndex(new Signature("save", "(I)V"));
        log.debug("[TargetFastClass] 方法save(I)V的索引:{}", targetIngB);
        Object obB = targetFastClass.invoke(targetIngB, fatherA, new Object[]{Integer.MAX_VALUE});
        log.debug("[TargetFastClass] 调用结果:{}", obB);

        // -------------------- 场景5:手动代理FastClass(模拟CGLIB的代理类FastClass) --------------------
        log.info("\n===== 场景5:ProxyFastClass(手动代理类FastClass) invokeSuper 方式 =====");
        CglibAgentProxyProxyFastClass proxyProxyFastClass = new CglibAgentProxyProxyFastClass();
        int proxyIngA = proxyProxyFastClass.getIndex(new Signature("superSave", "()V"));
        log.debug("[ProxyFastClass] 方法superSave()V的索引:{}", proxyIngA);
        Object obC = proxyProxyFastClass.invoke(proxyIngA, subB, new Object[0]);
        log.debug("[ProxyFastClass] 调用结果:{}", obC);

        int proxyIngB = proxyProxyFastClass.getIndex(new Signature("superSave", "(I)V"));
        log.debug("[ProxyFastClass] 方法superSave(I)V的索引:{}", proxyIngB);
        Object obD = proxyProxyFastClass.invoke(proxyIngB, subB, new Object[]{Integer.MAX_VALUE});
        log.debug("[ProxyFastClass] 调用结果:{}", obD);

        log.info("\n===== 所有CGLIB代理场景测试完成 =====");
    }

    // 目标父类(被代理类)
    @Slf4j
    static class CglibAgentProxyFatherA {
        /**
         * 无参保存方法
         */
        public void save() throws Throwable {
            log.info("CglibAgentProxyFatherA.save() 执行");
        }

        /**
         * int参数保存方法
         */
        public void save(int i) throws Throwable {
            log.info("CglibAgentProxyFatherA.save(int) 执行,参数:{}", i);
        }

        /**
         * long参数保存方法
         */
        public void save(long l) throws Throwable {
            log.info("CglibAgentProxyFatherA.save(long) 执行,参数:{}", l);
        }
    }

    // 子类A:手动反射调用父类方法的CGLIB代理
    @EqualsAndHashCode(callSuper = true)
    @Data
    static class CglibAgentProxySubA extends CglibAgentProxyFatherA {
        private MethodInterceptor methodInterceptor;

        // 静态缓存父类方法(避免重复反射查找)
        static Method save;
        static Method saveInt;
        static Method saveLong;

        static {
            try {
                // 手动获取父类方法(模拟CGLIB生成代理类时的方法解析)
                save = CglibAgentProxyFatherA.class.getMethod("save");
                saveInt = CglibAgentProxyFatherA.class.getMethod("save", int.class);
                saveLong = CglibAgentProxyFatherA.class.getMethod("save", long.class);
                log.debug("[CglibAgentProxySubA] 静态初始化完成,已缓存父类方法");
            } catch (NoSuchMethodException e) {
                throw new RuntimeException("父类方法查找失败", e);
            }
        }

        // 重写无参save方法(CGLIB生成的代理类会重写所有非final方法)
        @Override
        public void save() throws Throwable {
            /* 调用拦截器的intercept方法,传递:
             *  obj: 代理对象本身(CGLIB生成的子类实例)
             *  method: 被拦截的方法(此处为save())
             *  args1: 方法参数(无参时为空数组)
             *  proxy: MethodProxy实例(此处未使用,因为手动反射调用)
             * */
            methodInterceptor.intercept(this, save, new Object[0], null);
        }

        // 重写int参数save方法
        @Override
        public void save(int i) throws Throwable {
            methodInterceptor.intercept(this, saveInt, new Object[]{i}, null);
        }

        // 重写long参数save方法
        @Override
        public void save(long l) throws Throwable {
            methodInterceptor.intercept(this, saveLong, new Object[]{l}, null);
        }
    }

    // 子类B:使用MethodProxy优化的CGLIB代理
    @EqualsAndHashCode(callSuper = true)
    @Data
    static class CglibAgentProxySubB extends CglibAgentProxyFatherA {
        private MethodInterceptor methodInterceptor;

        // 缓存父类方法(用于MethodProxy创建)
        static Method save;
        static Method saveInt;
        static Method saveLong;
        // 缓存MethodProxy实例(CGLIB生成代理类时会为每个方法生成对应的MethodProxy)
        static MethodProxy saveMethodProxy;
        static MethodProxy saveMethodProxyInt;
        static MethodProxy saveMethodProxyLong;

        static {
            try {
                // 1. 获取父类方法(用于MethodProxy创建时指定目标方法)
                save = CglibAgentProxyFatherA.class.getMethod("save");
                saveInt = CglibAgentProxyFatherA.class.getMethod("save", int.class);
                saveLong = CglibAgentProxyFatherA.class.getMethod("save", long.class);

                /* 2. 创建MethodProxy实例(CGLIB核心优化点)
                 * 参数说明:
                 * - superClass: 父类(目标类)
                 * - proxySuperClass: 代理类(当前子类)
                 * - signature: 方法描述符(返回值+参数类型)
                 * - methodName: 代理类中调用的方法名(用于super调用)
                 * - altMethodName: 备用方法名(一般与methodName相同)
                 */
                saveMethodProxy = MethodProxy.create(
                        CglibAgentProxyFatherA.class,
                        CglibAgentProxySubB.class,
                        "()V",    // 方法描述符:返回void,无参数
                        "save",   // 代理类中调用的方法名(对应下面的superSave)
                        "superSave" // 实际要调用的父类方法名(通过super调用)
                );
                saveMethodProxyInt = MethodProxy.create(
                        CglibAgentProxyFatherA.class,
                        CglibAgentProxySubB.class,
                        "(I)V",   // 方法描述符:返回void,int参数
                        "save",
                        "superSave"
                );
                saveMethodProxyLong = MethodProxy.create(
                        CglibAgentProxyFatherA.class,
                        CglibAgentProxySubB.class,
                        "(J)V",   // 方法描述符:返回void,long参数(J是long的类型描述符)
                        "save",
                        "superSave"
                );
                log.debug("[CglibAgentProxySubB] 静态初始化完成,已创建MethodProxy实例");
            } catch (NoSuchMethodException e) {
                throw new RuntimeException("父类方法查找失败", e);
            }
        }

        // 代理类需要实现的super方法(供MethodProxy.invokeSuper调用)
        public void superSave() throws Throwable {
            super.save();  // 调用父类的无参save方法
        }

        public void superSave(int i) throws Throwable {
            super.save(i); // 调用父类的int参数save方法
        }

        public void superSave(long l) throws Throwable {
            super.save(l); // 调用父类的long参数save方法
        }

        // 重写无参save方法(CGLIB生成的代理类会重写此方法)
        @Override
        public void save() throws Throwable {
            // 调用拦截器的intercept方法,传递MethodProxy实例
            methodInterceptor.intercept(this, save, new Object[0], saveMethodProxy);
        }

        // 重写int参数save方法
        @Override
        public void save(int i) throws Throwable {
            methodInterceptor.intercept(this, saveInt, new Object[]{i}, saveMethodProxyInt);
        }

        // 重写long参数save方法
        @Override
        public void save(long l) throws Throwable {
            methodInterceptor.intercept(this, saveLong, new Object[]{l}, saveMethodProxyLong);
        }
    }

    // 手动实现的FastClass(模拟CGLIB的FastClass机制)
    static class CglibAgentProxyTargetFastClass {
        // 预定义方法签名与索引的映射(CGLIB会预生成此映射表)
        private static final Map<Signature, Integer> SIGNATURE_INDEX_MAP = new HashMap<>();

        static {
            SIGNATURE_INDEX_MAP.put(new Signature("save", "()V"), 0);
            SIGNATURE_INDEX_MAP.put(new Signature("save", "(I)V"), 1);
            SIGNATURE_INDEX_MAP.put(new Signature("save", "(J)V"), 2);
        }

        /**
         * 模拟CGLIB FastClass的getIndex方法:通过方法签名快速获取预计算的索引
         *
         * @param sig 方法签名(方法名+参数类型)
         * @return 方法索引(对应调用数组的位置)
         */
        public int getIndex(Signature sig) {
            Integer index = SIGNATURE_INDEX_MAP.get(sig);
            if (index == null) {
                throw new RuntimeException("未找到方法:" + sig);
            }
            log.debug("[TargetFastClass.getIndex] 方法 {} 对应索引:{}", sig, index);
            return index;
        }

        /**
         * 模拟CGLIB FastClass的invoke方法:通过索引直接调用目标方法(非反射)
         *
         * @param index 方法索引(来自getIndex)
         * @param obj   目标对象(FatherA实例)
         * @param args  方法参数
         * @return 方法调用结果
         */
        public Object invoke(int index, Object obj, Object[] args) throws Throwable {
            CglibAgentProxyFatherA target = (CglibAgentProxyFatherA) obj;
            switch (index) {
                case 0 -> {  // 对应save()V
                    target.save();
                    return null;
                }
                case 1 -> {  // 对应save(I)V
                    target.save((Integer) args[0]);
                    return null;
                }
                case 2 -> {  // 对应save(J)V
                    target.save((Long) args[0]);
                    return null;
                }
                default -> throw new RuntimeException("无效的方法索引:" + index);
            }
        }
    }

    // 手动实现的代理类FastClass(模拟CGLIB的代理类FastClass)
    static class CglibAgentProxyProxyFastClass {
        // 预定义代理类super方法签名与索引的映射
        private static final Map<Signature, Integer> SIGNATURE_INDEX_MAP = new HashMap<>();

        static {
            SIGNATURE_INDEX_MAP.put(new Signature("superSave", "()V"), 0);
            SIGNATURE_INDEX_MAP.put(new Signature("superSave", "(I)V"), 1);
            SIGNATURE_INDEX_MAP.put(new Signature("superSave", "(J)V"), 2);
        }

        /**
         * 模拟代理类FastClass的getIndex方法
         */
        public int getIndex(Signature sig) {
            Integer index = SIGNATURE_INDEX_MAP.get(sig);
            if (index == null) {
                throw new RuntimeException("未找到super方法:" + sig);
            }
            log.debug("[ProxyFastClass.getIndex] 方法 {} 对应索引:{}", sig, index);
            return index;
        }

        /**
         * 模拟代理类FastClass的invoke方法:通过索引调用代理类的super方法
         */
        public Object invoke(int index, Object obj, Object[] args) throws Throwable {
            CglibAgentProxySubB proxy = (CglibAgentProxySubB) obj;
            switch (index) {
                case 0 -> {  // 对应superSave()V
                    proxy.superSave();
                    return null;
                }
                case 1 -> {  // 对应superSave(I)V
                    proxy.superSave((Integer) args[0]);
                    return null;
                }
                case 2 -> {  // 对应superSave(J)V
                    proxy.superSave((Long) args[0]);
                    return null;
                }
                default -> throw new RuntimeException("无效的super方法索引:" + index);
            }
        }
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到