在运行时将新方法和属性注入类中

有没有什么办法可以在运行时将新的方法和属性注入到类中。

http://nurkiewicz.blogspot.com/2009/09/injecting-methods-at-runtime-to-java.html声明我们可以通过使用Groovy来做到这一点。

只使用Java就可以了吗?

只使用Java就可以了吗?

简单的答案是强调“你不想这样做!”。

这在技术上是可行的,但并非没有采用极其复杂,昂贵和脆弱的技巧,如字节码修改1 。 即便如此,您还必须依靠动态加载来访问修改后的类型和(可能)reflection以利用其新成员。 简而言之,你会为自己创造很多痛苦,只要收获很少。

Java是一种静态类型语言,添加/修改类类型签名可能会破坏类的静态类型。


1 – AspectJ等允许您向类中注入其他行为,但它可能不是您所追求的“运行时”注入。 当然,注入的方法不能用于静态编译的代码来调用。

所以,如果你真的疯了,你可以做一些类似于他们在这里概述的内容。 你可以做的是加载.java文件,找到正确的插入点,添加你需要的任何方法,调用java编译器并重新加载类。 祝好运调试那个烂摊子:)

编辑 这实际上可能有用……

你可以使用AOP做一些非常时髦的事情,虽然在运行时对类进行真正的修改是一种非常多毛的技术,需要大量的类加载魔法和手法。

更容易的是使用AOP技术生成目标类的子类,并将新方法引入其中,而AOP称为“mixin”或“introduction”。 请参阅此处阅读Spring AOP是如何做到的,尽管与您实际尝试实现的相比,这可能相当蹩脚。

只使用Java就可以了吗?

很简单,你要做的“唯一”事情是定义一个提供适当的ClassFileTransformer的检测代理 ,你必须使用reflection来调用添加的方法。 可能性并不是你想要做的事情,但它是可行的,并且它有一个定义明确的界面。 如果您想修改现有方法,您可能会对AspectJ感兴趣。

虽然它有可能,但它没有用。

您将如何访问这些新字段和方法?

您不能直接使用这些方法和字段(作为“普通”字段和方法),因为它们不会被编译。

如果您只想添加“属性”和“方法”,则可以使用Map作为“动态属性”,使用Map作为“动态方法”,以及按名称查找它们。

如果需要Java的扩展语言,可以添加嵌入式动态语言(如Javascript或Groovy); 其中大多数可以访问任意java对象和方法。