在Java中运行时合成新方法?

时间:2012-09-18 21:54:15

标签: java

  

可能重复:
  Can a Java class add a method to itself at runtime?

是否可以在运行时为Java中的类合成新方法?是否有图书馆可以实现这一目标?

2 个答案:

答案 0 :(得分:3)

进入已加载的课程?据我所知。

但是,您可能对生成新课程感兴趣。我看到两个选择:

  • 我最近创建了一个项目,它根据包含代码的String生成一个类,并将其加载到系统中,然后运行它的main方法。但是,这需要安装JDK =高度不可靠
  • 通过BCEL。这也有坏处,但整体似乎更好。它要求您事先获得方法的字节码。现在你可以做一些技巧,例如,制作一个方法
像这样:

public static void printTest() {
    System.out.println("Hey!");
}

然后看一下字节码,看看ConstantPool中的哪个位置“嘿!”存储,然后获取方法的字节码,将其缓存到字节数组中,然后动态创建具有预定义字节+常量池(您之前检查过)的方法,并使用您的字符串修改constantpool。对于更复杂的方法,这会非常快速地变得非常棘手(注意:可以通过改变它调用的方法或者获取字段来完成同样的操作,例如更改为错误)

因为我认为没有任何好的选择,所以这些是你最好的选择

答案 1 :(得分:2)

除了字节码工程库之外,如果你有一个类的接口,你可以使用Java的Proxy类。

使用界面:

public interface Foo {
    void bar();
}

具体课程:

class FooImpl {
    public void bar() {
        System.out.println("foo bar");
    }
}

要处理调用的方法,请使用InvocationHandler

class FooInvocationHandler implements InvocationHandler {

    private Foo foo;

    FooInvocationHandler(Foo foo) {
        this.foo = foo;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
        if (method.getName().equals("bar"))
            System.out.println("foo me");
            // return null if you don't want to invoke the method below
        }
        return method.invoke(foo, args); // Calls the original method
    }
}

然后创建FooFactory以使用Proxy生成并包装FooImpl个实例:

public class FooFactory {
    public static Foo createFoo(...) {
        Foo foo = new FooImpl(...);
        foo = Proxy.newProxyInstance(Foo.class.getClassLoader(),
                new Class[] { Foo.class },
                new FooInvocationHandler(foo));
        return foo;
    }
}

这将包装FooImpl对象,以便:

Foo foo = FooFactory.createFoo(...);
foo.bar();

打印:

foo me
foo bar

这是BCEL库的替代品,它可以做到这一点以及更多,包括从运行时信息生成类,但BCEL库不是本机的。 (Proxy自1.3以来就在java.lang.reflect所有内容。)