簡體   English   中英

編譯的Groovy腳本

[英]Compiled Groovy Scripts

據我了解,至少有2種方法可以用Java編譯Groovy腳本。

  1. 使用javax.script.ScriptEngine轉換為CompiledScript

     ScriptEngine engine = new ScriptEngineManager().getEngineByName("Groovy"); Bindings bindings = new SimpleBindings(); bindings.put("foo", 1234); Compilable compEngine = (Compilable)engine; CompiledScript cs = compEngine.compile("if (foo == 1234) true else false"); cs.eval(bindings); 
  2. 使用GroovyClassLoader#parse ,做一些中間工作,然后調用GroovyObject#invokeMethod(String, Object[])

注意-以下代碼來自Groovy in Action 我發現這是一本學習Groovy的好書。

GroovyClassLoader gcl = new GroovyClassLoader();
// Note, assume that the Groovy script gets compiled to a class that 
// includes a method, "do". And "do" accepts an `Integer` argument, "foo."
Class foo             = gcl.parseClass("if (foo == 1234) true else false");
GroovyObject hello    = (GroovyObject) foo.newInstance();
Object[] args         = { Integer.valueOf(1234) };
assert                  true == (foo.invokeMethod("do", args)); 

據我了解這兩種方法之間的差異,第一個方法涉及用key-value對(變量名到值)填充Bindings映射。 然后,我們通過CompiledScript#eval(Bindings)執行CompiledScript ,其中Bindings參數會發生突變。

但是,假設我想將Foo類對象傳遞給方法Foo#do 並且,而不是評估if (foo == 1234) ... ,我需要在源代碼中編寫:

if(fooObj.getFoo() == 1234) ...

然后,結果發現我需要對DSL進行后處理 ,以包括獲取foo的正確方法。

總的來說,根據我上面的示例,有沒有更簡單的方法可以實現第二種方法?

實際上有2個以上的選項。 所有文檔均在文檔中進行了描述(請參閱http://docs.groovy-lang.org/2.3.8/html/documentation/#_integrating_groovy_in_a_java_application ),但是無論如何,我都不會使用JSR-223(javax (.script),因為它是一個非常差的集成機制。

例如,使用GroovyShellGroovyClassLoader ,您可以設置自己的基本腳本類,這將使您非常輕松地設置foo實例,但是您也可以從基本腳本類中調用任何方法。

順便說一句,所有的Groovy腳本將實施的方法不do ,但run 因此,假設您具有以下基類:

public abstract class MyDSL extends groovy.lang.Script {
    Object fooObj
    public void setFooObj(Object foo) { fooObj = foo; }
    public Object getFooObj() { return fooObj; }
}

Foo的Holder類是這樣的:

public class FooHolder {
    def getFoo() { return 1234; }
}

那么您可以通過以下方式創建腳本:

CompilerConfiguration config = new CompilerConfiguration();
config.setScriptBaseClass("test.MyDSL");
GroovyClassLoader gcl = new GroovyClassLoader(this.getClass().getClassLoader(),config);
Class<? extends MyDSL> scriptClass = gcl.parseClass("return (fooObj.getFoo()==1234)");
MyDSL v1 = scriptClass.newInstance();
v1.setFooObj(new FooHolder());
Object result = v1.run();

請注意,這實際上是執行此操作的一種方法,但不一定是您需要的最佳方法。 也許您可以描述更多您想要實現的目標,但是Groovy有很多選擇,從像這樣的腳本到擴展自己的類或接口的類。 看一下文檔,讓我們知道。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM