嵌入Groovy
原文鏈接 譯者: 李璟(jlee381344197@gmail.com)
Groovy就其本身而言,在不同的場景下都算是一門非常不錯的編程語言,特別是在與Java混用的環境下,Groovy顯得更加強大。出于這種考慮,Groovy被設計成非常輕量級,并且易于嵌入到任何Java應用系統中。
目前主要有3種方法將Groovy與Java集成起來,細節會在下文中討論。
還有一種可選方案是,如果你確實需要使用其他腳本語言,可以利用Bean Scripting Framework將任何腳本語言集成到你的Java代碼中(雖然我們難以想象這么做的原因)。
利用shell執行腳本或者表達式
你可以使用GroovyShell執行Groovy中的任何表達式或者腳本。
GroovyShell允許你通過Binding對象傳進和傳出變量。
// call groovy expressions from Java code Binding binding = new Binding();binding.setVariable("foo", new Integer(2));
GroovyShell shell = new GroovyShell(binding);
Object value = shell.evaluate("println 'Hello World!'; x = 123; return foo * 10");
assert value.equals(new Integer(20));
assert binding.getVariable("x").equals(new Integer(123));</pre>
利用一個常用基類執行腳本
將Groovy腳本繼承自一個你選擇的基類,之后便可以訪問腳本的常規方法,這種做法往往非常有用。可以通過在編譯配置中設置腳本基類屬性,并將新的編譯配置傳遞給shell完成這一操作。
class ScriptBaseTest {@Test void extend_groovy_script() { def configuration = new CompilerConfiguration() configuration.setScriptBaseClass("ScriptBaseTestScript") def shell = new GroovyShell(this.class.classLoader, new Binding(), configuration) assertEquals shell.evaluate("foo()"), "this is foo" }
}
abstract class ScriptBaseTestScript extends Script {
def foo() { "this is foo" }
}</pre>
在Java中動態加載和運行Groovy腳本
你可以在Java代碼中直接使用GroovyClassLoader動態地加載和執行Groovy類。Java代碼如下:
ClassLoader parent = getClass().getClassLoader();GroovyClassLoader loader = new GroovyClassLoader(parent);
Class groovyClass = loader.parseClass(new File("src/test/groovy/script/HelloWorld.groovy"));
// let's call some method on an instance GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
Object[] args = {};
groovyObject.invokeMethod("run", args);</pre>
如果你想在Java里使用一個接口,但是接口的實現在Groovy腳本中,可以這樣:
GroovyClassLoader gcl = new GroovyClassLoader();Class clazz = gcl.parseClass(myStringwithGroovyClassSource, "SomeName.groovy");
Object aScript = clazz.newInstance();
MyInterface myObject = (MyInterface) aScript;
myObject.interfaceMethod();
...</pre>
如果這個Groovy類實現了接口MyInterface,這么做是沒有問題的。從現在開始myObject可以像其他實現了MyInterface接口的類一樣使用。
需要注意的一點是,parseClass 方法會從你的字符串文件名中創建一個對象。另一個gcl.parseClass的用法是:
Class clazz = gcl.parseClass(new File("SomeName.groovy");完整的例子如下所示:
TestInterface.javapublic interface TestInterface {
public void printIt();
}
Tester.groovy
public class Tester implements TestInterface {
public void printIt() { println "this is in the test class"; }
}
TestClass.java -- inside of a method
String fileName = "Tester.groovy";
GroovyClassLoader gcl = new GroovyClassLoader();
Class clazz = gcl.parseClass(new File(fileName));
Object aScript = clazz.newInstance();
TestInterface ifc = (TestInterface) aScript;
ifc.printIt();</pre>
請注意,所有的異常處理都已經被移除了,你不必在Java類中關心這個。實際上我會在一個工具類中完成Groovy的接口調用。
GroovyScriptEngine
如果開發人員想把Groovy腳本嵌入到服務器內,并且在腳本變更之后也能夠重新加載,GroovyScriptEngine是一個主要的解決方案。你可以使用一個CLASSPATH集合(url或者路徑名稱)初始化GroovyScriptEngine,之后便可以執行這些路徑中的Groovy腳本了。GroovyScriptEngine同樣可以跟蹤相互依賴的腳本,如果其中一個被依賴的腳本發生變更,則整個腳本樹都會被重新編譯和加載。
此外,每次腳本的執行,還可以利用一個腳本可以訪問的包含了最新參數的Binding對象傳遞信息。例子如下:
/my/groovy/script/path/hello.groovy:output = "Hello, ${input}!"
import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;
String[] roots = new String[] { "/my/groovy/script/path" };
GroovyScriptEngine gse = new GroovyScriptEngine(roots);
Binding binding = new Binding(); binding.setVariable("input", "world");
gse.run("hello.groovy", binding); System.out.println(binding.getVariable("output"));</pre>
輸出是“Hello, world!”。
在Java應用程序中嵌入Groovy控制臺
可以將一個交互式Groovy解釋器嵌入到運行中的應用程序中,以便調試和測試。請參考例子Embedding a Groovy Console in a Java Server Application,這是一個包含了示例代碼的教程。將Groovy作為腳本語言嵌入到應用程序中的例子也可以參考Integrating Groovy in an application – a success story。
運行時的依賴
你可以把groovy-all-x.y.z.jar拷貝到Groovy的安裝目錄中,也可以從Gradle / Maven / Ant+Ivy中查找相應的包的路徑執行構建。關于如何獲取Groovy,請查看download小節。