嵌入Groovy

jopen 9年前發布 | 29K 次閱讀 Groovy Java開發

原文鏈接 譯者: 李璟(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.java

public 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小節。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!