在Java中运行时合成新方法?
可能重复:
Java类可以在运行时向自己添加方法吗?
是否可以在运行时为Java中的类合成新方法? 有没有图书馆可以做到这一点?
除了字节码工程库之外,如果您有类的接口,则可以使用Java的Proxy
类。
有了界面:
public interface Foo { void bar(); }
具体课程:
class FooImpl { public void bar() { System.out.println("foo bar"); } }
要处理InvocationHandler
的方法,请使用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 } }
然后使用Proxy
创建一个FooFactory
来生成和包装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
。)
进入已装载的课程? 不是我的知识。
但是,您可能有兴趣生成一个新类。 我看到两个选择:
- 我最近创建了一个项目,它根据包含代码的String生成一个类,并将其加载到系统中,然后运行它的main方法。 但是,这需要安装JDK =非常不可靠
- 通过BCEL。 这也有坏处,但整体看起来似乎更好。 它要求您事先获得方法的字节码。 现在你可以做一些技巧,例如,制作一个方法
像这样:
public static void printTest() { System.out.println("Hey!"); }
然后看看字节码,看看ConstantPool中的哪个位置“嘿!” 存储,然后获取方法的字节码,将其缓存到字节数组中,然后动态创建一个带有预定义字节+常量池(您之前检查过)的方法,并使用您的字符串修改constantpool。 对于更复杂的方法,这会变得非常棘手(注意:可以更改它调用的方法,或者获取字段,例如更改为错误)
因为就我看来,没有任何好的选择,所以这些是你最好的选择