Java调用Groovy的方法总结

很多情况下,Groovy是执行某一类任务的理想工具,如快速原型开发设计(rapid prototyping)或创建可由宏指令(macros)或插件(plug-ins)扩展的模块应用。这些扩展可以用Groovy实现,而不需冗长乏味的开发部署周期便可嵌入到您的应用程序中。相信,Groovy极富表现力,其简洁性和强大特性会给您的程序开发带来很大的好处。

在其他情况下,Groovy或许不是最好的选择。这一点对高性能要求极高的应用尤其适用,因为在灵活性和运行速度之间权衡取舍是不可避免的。

Groovy最大的亮点便是与Java的完美集成。Groovy的灵活性和机动性,让开发者至少可以通过5种方式实现与Java集成,当然各种方式均有其优缺点。下面章节将详细讨论这5种集成方式,并给出各种方式的适用条件。

编译成字节码(Compilingto Bytecode)

最简单直接的集成方法便是把Groovy文件编程成Java字节码(即.class文件),并能够在Java类路径(classpath)获取这些文件。这种方式也有弊端:一方面您必须首先编译所有的Groovy文件,而与此同时,部分Groovy文件中引用了其他的Java类同样也需要先被编译,这时便会出现编译问题。

使用GroovyShell(UsingGroovyShell)

GroovyShell允许在Java类中(甚至Groovy类)求任意Groovy表达式的值。您可使用Binding对象输入参数给表达式,并最终通过GroovyShell返回Groovy表达式的计算结果。清单2.19展示了如何使用GroovyShell。

清单2.19 GroovyShell应用

import groovy.lang.Binding;

import groovy.lang.GroovyShell;

 

public class GroovyShellExample {

  public static void main(String args[]) {

    Binding binding = newBinding();

    binding.setVariable("x",10);

   binding.setVariable("language", "Groovy");

    GroovyShell shell = newGroovyShell(binding);

    Object value =shell.evaluate

      ("println\"Welcome to $language\"; y = x * 2; z = x * 3; return x ");

    assert value.equals(10);

    assertbinding.getVariable("y").equals(20);

    assertbinding.getVariable("z").equals(30);

  }
}


GroovyShell是推求动态类型表达式的有效工具。典型的应用就是推求用户输入Groovy动态表达式的值,通常会有一个用户界面(user interface,UI),如电子表格程序(spreadsheet application)。

使用GroovyScriptEngine(UsingGroovyScriptEngine)

GroovyShell多用于推求对立的脚本或表达式,如果换成相互关联的多个脚本,使用GroovyScriptEngine会更好些。GroovyScriptEngine从您指定的位置(文件系统,URL,数据库,等等)加载Groovy脚本,并且随着脚本变化而重新加载它们。如同GroovyShell一样,GroovyScriptEngine也允许您传入参数值,并能返回脚本的值。

假设您有一个简单的Groovy脚本,C:\tmp\SimpleScript.groovy,具体如下:

//SimpleScript.groovy

println "Welcome to $language"
return "The End"

清单2.20演示了如何传入参数给GroovyScriptEngine,并执行SimpleScript.groovy脚本,然后返回一个值。

清单2.20 GroovyScriptEngineExample.java

import groovy.lang.Binding;

import groovy.util.GroovyScriptEngine;

 

public class GroovyScriptEngineExample {

 

  public static voidmain(String args[]) {

    try {

      GroovyScriptEngineengine = new GroovyScriptEngine("");

      Binding binding = newBinding();

     binding.setVariable("language", "Groovy");

      Object value =engine.run("SimpleScript.groovy", binding);

      assertvalue.equals("The End");

    } catch (Exception e) {

      e.printStackTrace();

    }

  }

}


尽管GroovyScriptEngine是执行多个Groovy脚本的有效方法,但仍不能妥善处理复杂类。对于同时处理Groovy类和脚本的情况,最完善的解决方案便是GroovyClassLoader(其实,GroovyShell和GroovyScriptEngine都会用到它)

使用GroovyClassLoader(UsingGroovyClassLoader)

GroovyClassLoader是一个定制的类装载器,负责解释加载Java类中用到的Groovy类。它也能编译。清单2.21展示了如何使用GroovyClassLoader加载Groovy类并且调用该类的一个方法。

清单2.21GroovyClassLoader应用

//GroovySimpleFileCreator.groovy

 

class GroovySimpleFileCreator {

  public createFile(StringfileName){

    File file = newFile(fileName);

    file.createNewFile();

  }

}

 

//GroovyClassLoaderExample.java

 

import groovy.lang.GroovyClassLoader;

import groovy.lang.GroovyObject;

 

import java.io.File;

 

public class GroovyClassLoaderExample{

 

  public static voidmain(String args[]) {

    try {

      GroovyClassLoader loader= new GroovyClassLoader();

      Class fileCreator =loader.parseClass

        (newFile("GroovySimpleFileCreator.groovy"));

      GroovyObject object =(GroovyObject) fileCreator.newInstance();

     object.invokeMethod("createFile","C:\\temp\\emptyFile.txt");

    } catch (Exception e) {

      e.printStackTrace();

    }

  }

}


使用GroovyClassLoader典型的情景之一便是:您有一个Java接口和一个实现该Java接口的Groovy类。因此,您可以使用GroovyClassLoader加载Groovy实现类到应用中,这样便可直接调用接口的方法了,清单2.22给予形象地说明。

清单2.22 在Groovy中实现Java接口

//Shape.java:

 

public interface Shape{

  int calculateArea();

}

 

//Square.groovy:

 

class Square implements Shape {

 

  def x;

  int calculateArea(){

    return x * x;

  }

}

 

// GroovyClassLoaderExample2.java

 

import groovy.lang.GroovyClassLoader;

import groovy.lang.GroovyObject;

 

import java.io.File;

 

public class GroovyClassLoaderExample2{

 

  public static voidmain(String args[]) {

    try {

      GroovyClassLoader loader= new GroovyClassLoader();

      Class groovyClass =loader.parseClass(new File("Square.groovy"));

      GroovyObject object =(GroovyObject) groovyClass.newInstance();

      object.invokeMethod("setX", 10);

      Shape shape = (Shape)object;

      assertshape.calculateArea() == 100;

    } catch (Exception e) {

      e.printStackTrace();

    }

  }

}


使用JSR223(Using JSR 223)

如果您正在使用Java 6,就可以选择使用Sun’sJava Specification Request(JSR) 223:Scripting for theJava Platform。使用JSR 223可使您的应用与特定的脚本引擎实现很好的分离,使您轻松更换脚本语言。如果您想在Java代码中使用其他的脚本语言(如BeanShell或JRuby),还是推荐使用JSR 223。如果您没有使用Java 6而且还想选择多脚本语言混合编程,可以参考Apache’s Bean Scripting框架:http://jakarta.apache.org/bsf。除非要做到您的应用与特定的脚本引擎很好的解耦,否则使用Groovy自带的方式相对比较灵活些。

清单2.23展示了如何使用JSR223集成Groovy。您必须保证groovy-engine.jar文件已经在您的类路径中。您可到https://scripting.dev.java.net下载该jar文件。这个例子演示了如何调用Groovy方法,传递参数和返回一个值。

清单2.23 使用JSR 223

import javax.script.Invocable;

import javax.script.ScriptEngine;

import javax.script.ScriptEngineManager;

 

public class GroovyJSR223Example {

 

  public static voidmain(String args[]) {

    try {

      ScriptEngineManager factory= new ScriptEngineManager();

      ScriptEngine engine =factory.getEngineByName("groovy");

      String HelloLanguage ="def hello(language) {return \"Hello $language\"}";

     engine.eval(HelloLanguage);

      Invocable inv =(Invocable) engine;

      Object[] params = { newString("Groovy") };

      Object result =inv.invokeFunction("hello", params);

      assertresult.equals("Hello Groovy");

    } catch (Exception e) {

      // TODO Auto-generatedcatch block

      e.printStackTrace();

    }

  }

}


2.4本章小结

本章我简单介绍了Java与Groovy之间的部分重要的不同之处。您不要未完全掌握本章全部内容而担心,因为本书的余下部分将再次详细讨论这些内容。本章的目的就是让您理解“how Java is Groovy, while Groovy is not Java”,并且让您相信Groovy的确提供给Java程序员很多有价值的东西。

同时,本章也向您演示了如何让您的Groovy代码集成到Java代码中。当与Java集成时,您会发现Groovy极具灵活性和机动性。毕竟,Groovy的出现不是替代Java而是对Java的有效补充。

接下来,本书将深入讨论Groovy,并给出更加实用可扩展的实例,以帮助读者理解和灵活应用Groovy。下一章您将讨论Groovy数据类型(data types),集合(collections)和控制结构(control structures)。

你可能感兴趣的:(Java调用Groovy的方法总结)