Java反射:如何在运行时覆盖或生成方法?

时间:2009-06-28 11:49:25

标签: java reflection code-generation runtime

在普通Java中可以覆盖类的方法 在运行时以编程方式(甚至创建一个新方法)?

即使我在编译时知道这些类,我也希望能够这样做。

我的意思是在运行时覆盖:

abstract class MyClass{
  public void myMethod();
}

class Overrider extends MyClass{
  @Override
  public void myMethod(){}
}

class Injector{
  public static void myMethod(){ // STATIC !!!
    // do actual stuff
  }
}

// some magic code goes here
Overrider altered = doMagic(
    MyClass.class, Overrider.class, Injector.class);

现在,这个调用......

altered.myMethod();

...会调用 Injector.myMethod()而不是 Overrider.myMethod()

Injector.myMethod()是静态,因为在做了“魔术”之后 它是从不同的类实例调用的(它是Overrider), (所以我们阻止它访问本地字段)。

5 个答案:

答案 0 :(得分:10)

您可以使用类似cglib的内容来实时生成代码

答案 1 :(得分:9)

在java6中添加了转换任何已加载类的可能性。看一下java.lang.instrument包中的changes

答案 2 :(得分:8)

对于接口,有java.lang.reflect.Proxy

对于课程,您需要第三方库或编写相当多的代码。通常以这种方式动态创建类是为了测试创建模拟。

还有一个允许修改类的instrumentation API。您还可以使用自定义类加载器或仅使用磁盘上的类文件来修改类。

答案 3 :(得分:8)

我编写了一个article for java.net,关于如何在类加载器使用java代理加载日志语句时将其透明地添加到类中。

它使用Javassist库来操作字节代码,包括使用Javassist编译器生成额外的字节码,然后将其插入适当的位置,然后将生成的类提供给类加载器。

slf4j项目提供了精炼版本。

答案 4 :(得分:0)

如果我做对了,那么与您有关的主要问题是如何通过实例接口方法传递静态方法委托(如在C#中)。

您可以查看以下文章:A Java Programmer Looks at C# Delegates,其中介绍了如何获取静态方法的引用并调用它。然后,您可以创建一个包装类,在其构造函数中接受静态方法名称,并实现您的基类以从实例方法调用静态方法。