有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何获取cglib代理类实例的字节码?

我正在尝试使用BCEL以这种方式获取cglib增强对象的字节码:

package app;

import cglib.MyInterceptor;
import net.sf.cglib.proxy.Enhancer;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import service.Tool;

public class CgLibApp {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        // target object
        Tool tool = new Tool();

        // proxying
        Enhancer e = new Enhancer();
        e.setSuperclass(tool.getClass());
        e.setCallback(new MyInterceptor(tool));
        Tool proxifiedTool = (Tool) e.create();

        // trying to get proxy byte code
        JavaClass clazz = Repository.lookupClass(proxifiedTool.getClass());
        Method method = clazz.getMethod(Tool.class.getMethod("meth"));

        System.out.println(method.getCode().toString());
    }
}

但我得到了:

Exception in thread "main" java.lang.ClassNotFoundException: SyntheticRepository could not load service.Tool$$EnhancerByCGLIB$$22a3afcc
at org.apache.bcel.util.SyntheticRepository.loadClass(SyntheticRepository.java:174)
at org.apache.bcel.util.SyntheticRepository.loadClass(SyntheticRepository.java:158)
at org.apache.bcel.Repository.lookupClass(Repository.java:74)
at app.CgLibApp.main(CgLibApp.java:21)

我应该怎么做才能从增强对象中获取字节码


共 (2) 个答案

  1. # 1 楼答案

    BCEL查询类加载器中的.class文件,以获取表示该文件的字节数组。动态生成的类不存在这样的类文件

    为了获得类文件,必须在创建类文件的过程中收集字节码。Cglib构建在ASM之上,它允许您注册自己的ClassVisitor来收集类文件

    对于Enhancer,使用generateClass(ClassVisitor)方法并将后一种方法交给ClassWriter。调用该方法后,可以从传递的class writer对象获取字节码

  2. # 2 楼答案

    下面是打印生成的CGLIB类的伪代码的示例代码。 visitEnd方法以文本格式打印生成的类

    package naga.cglib.demo;
    
    import static org.objectweb.asm.Opcodes.ASM7;
    
    import java.io.PrintWriter;
    import java.lang.reflect.InvocationTargetException;
    
    import org.objectweb.asm.ClassVisitor;
    import org.objectweb.asm.FieldVisitor;
    import org.objectweb.asm.MethodVisitor;
    import org.objectweb.asm.util.TraceClassVisitor;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.FixedValue;
    
    public class App {
    public static void main(String[] args) throws Exception, IllegalArgumentException, InvocationTargetException {
    
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(SampleClass.class);
        enhancer.setCallback(new FixedValueImpl());
        SampleClass proxy = (SampleClass) enhancer.create();
        enhancer.generateClass(new CustomClassWriter());
    
        System.out.println("Hello cglib!" + proxy.test(null));
    
    }
    }
    
    class SampleClass {
    public String test(String input) {
        return "Hello world!";
    }
    }
    
    class FixedValueImpl implements FixedValue {
    
    @Override
    public Object loadObject() throws Exception {
        // TODO Auto-generated method stub
        return "Hello cglib! from loadObject()";
    }
    
    }
    
    class CustomClassWriter extends ClassVisitor {
    
    TraceClassVisitor tracer;
    PrintWriter pw = new PrintWriter(System.out);
    
    public CustomClassWriter() {
        super(ASM7);
        tracer = new TraceClassVisitor(pw);
    }
    
    @Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
        System.out.println("method name is :" + name);
        return tracer.visitMethod(access, name, desc, signature, exceptions);
    
    }
    
    @Override
    public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
    
        System.out.println("field name is :" + name);
        return tracer.visitField(access, name, desc, signature, value);
    }
    
    public void visitEnd() {
        tracer.visitEnd();
        System.out.println(tracer.p.getText());
    
    }
    }