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

Groovy與Java程式碼間的互操作(轉)

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

 

2   Groovy指令碼呼叫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>

 

3       Groovy指令碼呼叫Java程式碼

3.1     程式碼:

Test.groovy:

package org.nick;

class Test{

Test(){

b = new TestJ();

b.a();

}

static void 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.     說明:可行。理由同上。

  4      Java程式碼呼叫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();

     }

}