引言
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()
方法为例,原始父类方法的字节码可能是:
java
public void save() {
System.out.println("CglibAgentProxyFatherA.save() 执行");
}
CGLIB生成的重写方法的字节码会被修改为:
java
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()
方法为例,重写方法的字节码大致等价于:
java
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
字段); - 参数校验:检查参数类型是否匹配(如
int
转int
,long
转long
); - 安全检查:JVM验证调用者是否有权限访问该方法(如
public
方法无需检查); - 动态调用:通过
invokedynamic
或invokevirtual
指令执行方法。
- 方法查找:在
-
MethodProxy调用(场景2) :通过
MethodProxy.invoke(proxy, args)
调用。MethodProxy
内部维护了一个MethodAccessor
实例,该实例在首次调用时通过ASM生成的字节码直接调用父类方法(如invokespecial
指令调用父类的save()
方法),后续调用直接复用该字节码,避免了反射的开销。
三、MethodProxy的极致优化:字节码生成与内联缓存
MethodProxy
是CGLIB性能优化的核心,其底层通过动态生成调用字节码 替代反射。下面我们通过MethodProxy.invoke()
的源码和生成的字节码,深入理解其优化原理。
3.1 MethodProxy的创建:为每个方法生成专用调用器
MethodProxy.create()
方法的本质是为每个目标方法生成一个MethodProxy
实例,该实例内部持有一个MethodAccessor
。MethodAccessor
的生成过程如下:
3.1.1 生成调用类(InvocationHandler)
CGLIB会动态生成一个MethodAccessor
类,该类实现了MethodAccessor
接口(包含invoke()
方法)。例如,针对save()
方法,生成的MethodAccessor
类可能如下:
java
class MethodProxy$SaveMethodAccessor implements MethodAccessor {
public Object invoke(Object obj, Object[] args) throws Throwable {
// 直接调用父类的save()方法(非反射)
((CglibAgentProxyFatherA) obj).save();
return null;
}
}
3.1.2 字节码生成:ASM生成调用逻辑
MethodAccessor
的invoke()
方法通过ASM生成,其字节码直接调用父类的方法。例如,save()
方法的invoke()
字节码可能如下:
java
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()
方法。其核心步骤如下:
- 参数校验 :检查
obj
是否是目标类的实例(避免传入错误类型的对象); - 类型转换 :将
obj
转换为目标类类型(如CglibAgentProxyFatherA
); - 直接调用 :通过生成的字节码直接调用父类方法(如
target.save()
); - 结果返回 :将父类方法的返回值转换为
Object
类型返回(基本类型会自动装箱)。
3.3 MethodProxy.invokeSuper()的特殊场景
MethodProxy.invokeSuper(proxy, args)
用于调用代理类中重写的superXxx()
方法(如superSave()
)。其执行流程如下:
- 参数校验 :检查
proxy
是否是代理子类的实例; - 类型转换 :将
proxy
转换为代理子类类型(如CglibAgentProxySubB
); - 调用superXxx()方法 :执行代理子类的
superSave()
方法,该方法内部通过super
调用父类的原始方法; - 结果返回 :返回
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
为例:
java
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)
方法的实现:
java
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实例 :通过静态变量缓存
MethodProxy
和FastClass
实例,避免重复生成; - 监控代理性能 :使用Arthas等工具监控代理方法的调用耗时,定位性能瓶颈(如反射调用未替换为
MethodProxy
)。
六、总结:CGLIB代理的底层逻辑全景图
CGLIB代理的底层原理可以概括为以下步骤:
- 类生成:通过ASM动态生成目标类的子类,重写所有可代理方法;
- 方法拦截 :重写的方法内部调用
MethodInterceptor.intercept()
,插入前置/后置逻辑; - 父类方法调用 :通过
MethodProxy
(字节码生成)或反射调用父类方法,MethodProxy
通过预生成MethodAccessor
实现极致性能; - FastClass优化:通过预计算方法索引表,将方法调用转换为索引查找,进一步减少开销。
特性 | CGLIB代理 | JDK动态代理 |
---|---|---|
代理机制 | 继承目标类(生成子类) | 实现目标接口(生成代理接口实现) |
目标类限制 | 非final类、非final方法 | 必须实现接口 |
性能 | 更高(字节码生成、FastClass优化) | 较低(反射调用) |
适用场景 | 无接口的服务类代理 | 接口驱动的代理(如Spring MVC) |
通过这些机制,CGLIB实现了比JDK动态代理更高的性能,成为Spring AOP等框架的首选代理方案。理解其底层原理,有助于我们在实际开发中更高效地使用和调优CGLIB代理。
完整代码
java
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);
}
}
}
}