1. 程式人生 > >Groovy與Java程式碼間的互操作

Groovy與Java程式碼間的互操作

1Groovy互操作說明

Groovy指令碼有兩種呼叫方式,一是作為普通指令碼檔案(.groovy),使用Groovy提供的命令列groovy或者通過類groovy.lang.GroovyShell來呼叫。二是作為普通的Java類檔案(.class),用傳統的方式來呼叫,這需要先使用groovyc把指令碼檔案編譯成類檔案,然後再使用java命令來呼叫。

2Groovy指令碼呼叫Groovy指令碼

2.1程式碼:

Test.groovy

package org.nick;

class Test{

Test(){

t = new TestS();

t.a();

}

static

void main(String[] args){

t = new Test();

}

}

TestS.groovy

package org.nick;

class TestS{

void a(){

println("Hello World");

}

}

2.2使用groovy命令:

i.說明:不可行。由於groovy沒有提供指定classpath的引數,因此,當兩個groovy指令碼需要進行互相呼叫時,Test.groovy將不能找到他所需要的TestS.groovy的定義,因此,通過groovy命令,不能實現兩個指令碼間的直接呼叫。

2.3使用GroovyShell

i.說明:可行。由於GroovyShell是一標準的Java類,因此,我們可以通過指定classpath,來找到所需的類。但這裡有一個前提,被呼叫的指令碼需要事先編譯為.class檔案。

ii.例項:

<target name="run" depends="init">

<java classname="groovy.lang.GroovyShell">

<classpath refid="run.path"/>

<arg value="${src.dir}/org/nick/Test.groovy" />

</java>

</target>

注:classpath當中包含了GroovyShell所在的jar,和被呼叫指令碼編譯後類檔案的目錄。

2.4使用java命令:

i.說明:可行。由於所有的指令碼檔案都被編譯為了.class檔案,因此,我們可以像一般的情況那樣,在指令碼之間互相呼叫。

ii.例項:

<java classname="org.nick.Test">

<classpath refid="run.path"/>

</java>

3Groovy指令碼呼叫Java程式碼

3.1程式碼:

Test.groovy

package org.nick;

class Test{

Test(){

b = new TestJ();

b.a();

}

staticvoid main(String[] args){

t = new Test();

}

}

TestJ.java

package org.nick;

public class TestJ {

public void a(){

System.out.println("Hello");

}

}

3.2使用groovy命令:

i.說明:理論不可行。原因同上,由於groovy不能指定其他類所在的位置,所以理論上不可行。但實際上groovy指令碼內部是能夠呼叫java.*等包中的Java類的,也就是說只要我們把我們自己寫的Java類提前編譯了,並放到classpath所指定的位置,我們就能使用groovy命令來實現Groovy指令碼呼叫Java程式碼。

3.3使用GroovyShell

i.說明:可行。理由同上。只要把Java檔案提前編譯了即可。

3.4使用java命令:

i.說明:可行。理由同上。

4Java程式碼呼叫Groovy指令碼

4.1程式碼:

Groovy指令碼:

package org.nick;

for(it in args)

println(it)

Groovy類:

package org.nick;

class Test{

void a(name){

println("Hello ${name}");

}

}

4.2使用GroovyShell呼叫Groovy指令碼:

i.說明:通過GroovyShell類,我們可以在Java程式程式碼中直接載入和執行Groovy指令碼。而且,通過Binding類,我們還可以向Groovy指令碼傳遞引數的值。

ii.程式碼:

package org.nick;

public class GroovyTest {

public static void main(String[] args) throws Exception{

Binding binding = new Binding();

binding.setVariable("args", new String[]{"aaa","bbb","ccc"});

GroovyShell shell = new GroovyShell(binding);

Object obj = shell.evaluate(new File("src/org/nick/Test.groovy"));

}

}

4.3使用GroovyScriptEngine呼叫Groovy指令碼:

i.說明:GroovyScriptEngine是比GroovyShell更完整的一個方案,通過roots變數,我們指定了指令碼檔案所在的目錄,然後在需要執行時,GroovyScriptEngine將根據roots中的變數查詢並執行指定的指令碼檔案。同樣,我們可以通過Binding類為指令碼傳入引數。另外,有一點很重要的就是,當我們所呼叫的指令碼呼叫了另一指令碼時,如果使用GroovyShell方式且被呼叫指令碼未編譯為Java類,那麼將出現ClassNotFound錯誤,但如果使用GroovyScriptEngine,那麼當一指令碼呼叫另一指令碼時,即使另一指令碼未編譯為Java類,但只要他出現在roots變數所指向的位置,GroovyScriptEngine也能找到該對應的指令碼。

ii.程式碼:

package org.nick;

public class GroovyTest {

public static void main(String[] args) throws Exception {

String[] roots = new String[] { "src/org/nick" };

GroovyScriptEngine gse = new GroovyScriptEngine(roots);

Binding binding = new Binding();

binding.setVariable("args", new String[] { "aaa", "bbb", "ccc" });

gse.run("Test.groovy", binding);

}

}

4.4使用GroovyClassLoader載入Groovy類:

i.說明:通過GroovyClassLoader我們可以像在Java程式碼當中那樣,動態載入由Groovy指令碼書寫的類。並且通過對所裝載的類進行例項化,我們可以以一種類似於反射的方式來呼叫其內部的方法。

ii.程式碼:

package org.nick;

public class GroovyTest {

public GroovyTest() {

try {

ClassLoader parent = getClass().getClassLoader();

GroovyClassLoader loader = new GroovyClassLoader(parent);

Class groovyClass = loader.parseClass(new File

("src/org/nick/Test.groovy"));

GroovyObject groovyObject = (GroovyObject)

groovyClass.newInstance();

groovyObject.invokeMethod("a",new Object[]{"aaa"});

} catch (Exception e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

GroovyTest t = new GroovyTest();

}

}