Skip to content

字节码操作 - 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 对象)

注意事项

  1. CGLIB 代理限制

    • 不能代理 final 类
    • 不能代理 final 方法
    • 需要无参构造器
  2. 性能考虑

    • 代理类生成有开销
    • 首次创建较慢,后续复用
  3. 调试困难

    • 生成的类名包含 $$Enhancer
    • 堆栈跟踪较复杂

相关链接

基于 Apache 2.0 许可发布