字节码操作 - CGLIB/ASM/Objenesis
概述
Spring 内嵌了 CGLIB、ASM 和 Objenesis 等字节码操作库,用于实现动态代理、类增强和对象实例化。
核心能力矩阵
| 能力 | 核心类 | 解决的问题 | 使用频率 | 学习优先级 |
|---|---|---|---|---|
| 字节码操作 | CglibAopProxy | 动态代理 | ⭐⭐⭐ | 🟢 低 |
核心组件
CGLIB
用途
- 生成代理类(无需接口)
- 方法拦截
- 类增强
使用示例
java
// CGLIB 代理示例
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {
System.out.println("Before method: " + method.getName());
Object result = proxy.invokeSuper(obj, args);
System.out.println("After method: " + method.getName());
return result;
});
UserService proxy = (UserService) enhancer.create();ASM
用途
- 字节码分析和修改
- 类元数据读取
- 注解处理
使用场景
java
// Spring 使用 ASM 读取类元数据
ClassReader classReader = new ClassReader(className);
ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM9) {
@Override
public void visit(int version, int access, String name,
String signature, String superName, String[] interfaces) {
// 处理类信息
}
};
classReader.accept(classVisitor, ClassReader.SKIP_CODE);Objenesis
用途
- 绕过构造器创建对象
- 提高代理对象创建性能
- 支持无默认构造器的类
使用示例
java
// 使用 Objenesis 创建对象
Objenesis objenesis = new ObjenesisStd();
ObjectInstantiator instantiator = objenesis.getInstantiatorOf(MyClass.class);
MyClass instance = (MyClass) instantiator.newInstance();
// 注意:绕过构造器,字段为默认值Spring AOP 中的应用
java
// CGLIB 代理创建
public class CglibAopProxy implements AopProxy {
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false);
enhancer.setCallbacks(callbacks);
// 使用 Objenesis 创建实例
return createProxyInstance(enhancer);
}
}使用场景
- AOP 动态代理
- 延迟加载
- 对象池
- 测试(Mock 对象)
注意事项
CGLIB 代理限制:
- 不能代理 final 类
- 不能代理 final 方法
- 需要无参构造器
性能考虑:
- 代理类生成有开销
- 首次创建较慢,后续复用
调试困难:
- 生成的类名包含 $$Enhancer
- 堆栈跟踪较复杂