It is possible in plain Java to override a method of a class programmatically at runtime (or even create a new method)?
在普通Java中,可以在运行时以编程方式覆盖类的方法(甚至创建新方法)?
I want to be able to do this even if I don't know the classes at compile time.
即使我在编译时不知道类,我也希望能够这样做。
What I mean exactly by overriding at runtime:
我在运行时重写的意思是:
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);
Now, this invocation...
现在,这个调用......
altered.myMethod();
...would call Injector.myMethod() instead of Overrider.myMethod().
...将调用Injector.myMethod()而不是Overrider.myMethod()。
Injector.myMethod() is static, because, after doing "magic" it is invoked from different class instance (it's the Overrider), (so we prevent it from accessing local fields).
Injector.myMethod()是静态的,因为在执行“magic”之后,它会从不同的类实例(它是Overrider)调用,(因此我们阻止它访问本地字段)。
5 个解决方案
#2
In java6 has been added the possibility to transform any already loaded class. Take a look at the changes in the java.lang.instrument package
在java6中添加了转换任何已加载类的可能性。看一下java.lang.instrument包中的更改
#3
For interfaces there is java.lang.reflect.Proxy
.
对于接口,有java.lang.reflect.Proxy。
For classes you'll either need a third-party library or write a fair bit of code. Generally dynamically creating classes in this way is to create mocks for testing.
对于课程,您需要第三方库或编写相当多的代码。通常以这种方式动态创建类是为了测试创建模拟。
There is also the instrumentation API that allows modification of classes. You can also modify classes with a custom class loader or just the class files on disk.
还有一个允许修改类的instrumentation API。您还可以使用自定义类加载器或仅使用磁盘上的类文件来修改类。
#4
I wrote an article for java.net about how to transparently add logging statements to a class when it is loaded by the classloader using a java agent.
我为java.net撰写了一篇文章,介绍如何使用java代理程序在类加载器加载日志语句时将其透明地添加到类中。
It uses the Javassist library to manipulate the byte code, including using the Javassist compiler to generate extra bytecode which is then inserted in the appropriate place, and then the resulting class is provided to the classloader.
它使用Javassist库来操作字节代码,包括使用Javassist编译器生成额外的字节码,然后将其插入适当的位置,然后将生成的类提供给类加载器。
A refined version is available with the slf4j
project.
slf4j项目提供精炼版本。
#5
If I got it right, the main problem that concerns you is how to pass a static method delegate (like in C#), through the instance interface method.
如果我做对了,关注的主要问题是如何通过实例接口方法传递静态方法委托(如在C#中)。
You can check this article: A Java Programmer Looks at C# Delegates, which shows you how to get a reference to your static method and invoke it. You can then create a wrapper class which accepts the static method name in its constructor, and implements your base class to invoke the static method from the instance method.
您可以查看这篇文章:Java程序员查看C#Delegates,它向您展示如何获取对静态方法的引用并调用它。然后,您可以创建一个包装器类,该类在其构造函数中接受静态方法名称,并实现您的基类以从实例方法调用静态方法。
#1
You can use something like cglib for generating code on-the-fly
你可以使用像cglib这样的东西来实时生成代码
#2
In java6 has been added the possibility to transform any already loaded class. Take a look at the changes in the java.lang.instrument package
在java6中添加了转换任何已加载类的可能性。看一下java.lang.instrument包中的更改
#3
For interfaces there is java.lang.reflect.Proxy
.
对于接口,有java.lang.reflect.Proxy。
For classes you'll either need a third-party library or write a fair bit of code. Generally dynamically creating classes in this way is to create mocks for testing.
对于课程,您需要第三方库或编写相当多的代码。通常以这种方式动态创建类是为了测试创建模拟。
There is also the instrumentation API that allows modification of classes. You can also modify classes with a custom class loader or just the class files on disk.
还有一个允许修改类的instrumentation API。您还可以使用自定义类加载器或仅使用磁盘上的类文件来修改类。
#4
I wrote an article for java.net about how to transparently add logging statements to a class when it is loaded by the classloader using a java agent.
我为java.net撰写了一篇文章,介绍如何使用java代理程序在类加载器加载日志语句时将其透明地添加到类中。
It uses the Javassist library to manipulate the byte code, including using the Javassist compiler to generate extra bytecode which is then inserted in the appropriate place, and then the resulting class is provided to the classloader.
它使用Javassist库来操作字节代码,包括使用Javassist编译器生成额外的字节码,然后将其插入适当的位置,然后将生成的类提供给类加载器。
A refined version is available with the slf4j
project.
slf4j项目提供精炼版本。
#5
If I got it right, the main problem that concerns you is how to pass a static method delegate (like in C#), through the instance interface method.
如果我做对了,关注的主要问题是如何通过实例接口方法传递静态方法委托(如在C#中)。
You can check this article: A Java Programmer Looks at C# Delegates, which shows you how to get a reference to your static method and invoke it. You can then create a wrapper class which accepts the static method name in its constructor, and implements your base class to invoke the static method from the instance method.
您可以查看这篇文章:Java程序员查看C#Delegates,它向您展示如何获取对静态方法的引用并调用它。然后,您可以创建一个包装器类,该类在其构造函数中接受静态方法名称,并实现您的基类以从实例方法调用静态方法。