閱讀295 返回首頁    go 技術社區[雲棲]


嵌入Groovy

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));

利用一個常用基類執行腳本

將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"

    }

}

在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);

如果你想在Java裏使用一個接口,但是接口的實現在Groovy腳本中,可以這樣:

GroovyClassLoader gcl = new GroovyClassLoader(); 

Class clazz = gcl.parseClass(myStringwithGroovyClassSource, "SomeName.groovy"); 

Object aScript = clazz.newInstance(); 

MyInterface myObject = (MyInterface) aScript; 

myObject.interfaceMethod(); 

...

如果這個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();

請注意,所有的異常處理都已經被移除了,你不必在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"));

輸出是“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小節。

最後更新:2017-05-23 09:31:44

  上一篇:go  線程安全與共享資源
  下一篇:go  采用Java 8中Lambda表達式和默認方法的模板方法模式