使用 Groovy 动态更改 Java 应用程序的行为

Changing the behaviour of a Java app dynamically using Groovy

我正在研究动态 mod 验证 Java 应用程序行为的方法(具体来说,我正在尝试制作一个 Minecraft mod 允许用户 mod通过编写代码而不需要重新启动游戏来验证他们找到的对象的行为)我偶然发现了 Groovy。我的问题是:是否有可能以 "share" 反对的方式整合 Java 和 Groovy? (我正在考虑拥有一组特定的 类 实际上是 Groovy 代码,以便您可以在运行时更改代码,类似于您在任何 Smalltalk 实现中可以做的事情)

我不确定不用编译就可以用 Groovy 完成。您可以做到,但是 Groovy 的 "scripting" 方面对您没有帮助。我会考虑让玩家写 javascript 并使用 Java 的 ScriptEngine。看这里:http://docs.oracle.com/javase/7/docs/technotes/guides/scripting/programmer_guide/

看看Integrating Groovy in a Java Application。它显示了如何从 Java 应用程序内部 运行 一个 Groovy 脚本并使用 groovy.lang.Binding.

在它们之间共享数据的示例

是的,你可以做到。例如,您有一些用 java 编写的东西,它使用了来自比方说 spring 上下文的一些对象。所以现在你能做的是:

  • 在执行 java 代码之前执行 groovy 脚本,
  • 使用委托设计模式来包装它,覆盖一些方法
  • 终于把它放回上下文中。

所以基本上在执行您的 java 代码的那一刻,他将获得一个包装对象,其中包含一些在运行时进行的更改。

如果这就是您想要做的,请告诉我我可以为您编写一些示例代码。

多么酷的主意!

1. Groovy: Java和Groovy可以共享对象,来回调用。 Groovy class 实现 Java 接口的 es 很容易从 Java 调用。 (还有其他方法,比如从 Java 调用 groovyObject.invokeMethod("methodName", args)。)在 JVM 语言中,Groovy 与 Java 的集成最紧密。 Java 程序员也很容易学习,因为它与 Java.

有很多共同点

本书Groovy in Action has a chapter on "Integrating Groovy" that explains and compares the approaches (in more detail than the reference docs做):GroovyShell、GroovyScriptEngine、GroovyClassLoader、Spring集成和JSR- 223 脚本引擎管理器。 GroovyClassLoader 是最有能力的选择。

但是, 虽然在 运行 时很容易编译和加载 Groovy 代码,但我对如何更改现有对象的行为感到困惑实例(缺少下面关于 热插拔 的注释)。 (这可能取决于 class 是否覆盖 Java 接口或子 class 是 Java class。)考虑:

class G implements Runnable {
  void run() { println 'Groovy' }
}

g = new G()
g.run()

这会打印 Groovy。现在重新定义 class:

class G implements Runnable {
  void run() { println 'Groovy!' }
}

g1 = new G()
g.run()
g1.run()

这会打印

Groovy
Groovy!

现在使用 meta-class 在 运行 时间更改方法:

G.metaClass.run = { println 'Groovy!!!' }

g2 = new G()
g.run()
g1.run()
g2.run()

这会打印

Groovy
Groovy!
Groovy!

如果我们从那些 class 定义中省略 implements Runnable,那么最后一步将改为打印

Groovy
Groovy!
Groovy!!!

但是我们的 class 实现了 Runnable,现在做:

G.metaClass.run = { println 'Very Groovy!!!' }

g3 = new G()
g.run()
g1.run()
g2.run()
g3.run()

这会打印:

 Groovy
 Groovy!
 Very Groovy!!!
 Very Groovy!!!

解决方法是在 class 变量中保存的闭包中实现这些方法。

2。热交换: 如果要点是在 运行 时间为 class 现有实例重新定义方法体,那么您可以在 IDE 中简单地 运行 ]的调试器并使用热插拔.

例如对于 IntelliJ,这里是 Java 的 instructions to configure hot swapping 和 Groovy 代码。

3。扩展热交换: 如果你还想在 运行 时能够 add/remove 方法和实例变量,那么请看这个 JetBrains article on extended hot swapping via DCEVM (Dynamic Code Evolution VM).

查看 https://github.com/HotswapProjects

处的热插拔代码代码

另请参阅此 SO Q&A on hot swapping techniques