Groovy是构建在JVM上的一个轻量级却强大的动态语言.因为Groovy就是用Java写的,Groovy可以做到与Java的无缝兼容,可以使用Java强大的类库 而且Groovy最终也会被编译成class文件.
Groovy在1.0版的时候还存在性能问题,因为Groovy的很多实现都是用反射来做的,但是现在Groovy 1.1快推出了,据说快了10x...现在JetBrains也加入了Groovy Team旨在改善Groovy的性能,在Groovy2.0的时候还可能加上JIT,那性能就不成问题了,看来Groovy已经不是小打小闹了.而且随之而来的Grail.等基于Groovy的框架的推出,Groovy前景一片大好啊.
这篇文章不是为了讲Groovy的一些语法,而是说他怎么和Java做整合.
- 静态使用Groory
1.运行Groovy类.
Groovy最终是会被编译成Java 的Class类的,所以Java是可以直接使用Groovy的类的.
如下,先是一个Groovy类:
package com.test;
class TestGroovyHelloWorld {
def doit(){
println "hello world!"
}
}此类定义了一个doit方法,打印出hello world!字符串
然后看看Java怎么用这个类:
package com.test;
public class TestHelloWorld {
/**
* @param args
*/
public static void main(String[] args) {
TestGroovyHelloWorld test = new TestGroovyHelloWorld();
test.doit();}
}
运行一下,果然打出了hello world!
很简单吧,只要直接import就行了.hoho,而且定义一个GroovyBean比定义一个JavaBean要简单的多的多.
2.运行Groovy脚本
实际上和Groovy类差不多,只不过Groovy类是集成自GroovyObject,而Groovy脚本是集成GroovyScript的,实际看看例子吧
Groovy脚本:
package com.test;
println "$test hello world!"
也很简单,就是打出hello world!不同的时候前面加上了$test ,这个有点类似与FreeMarker的格式($test也可以写成${test}),作用也是一样,通过外部将test参数引入,可以将$test替换成一个对象.看看下面Java怎么做的吧:
public class TestMain {
/**
* @param args
*/
public static void main(String[] args) {
Binding b = new Binding();
b.setVariable("test", "Kevin");//向脚本中的$test传入对象"Kevin"
Script test = new TestScript(b);
test.run();
}
}打印出来一看是Kevin hello world!了..
-
动态使用Groovy
Groovy是一个动态的脚本语言,如果只是向上面那样静态的使用,那优势就少了一半,既然是动态语言,那就看看怎么动态的去使用Groovy吧
1.通过接口,动态载入并使用Groovy类
(1)、定义Java接口包含在Java中需要调用的Groovy方法
public interface IFoo {
public Object run(Object foo);
}
(2)、创建Groovy类实现该接口class Foo implements IFoo {
public Object run(Object foo) {
println 'Hello World!'
x = 123
foo * 10
}
}(3)、动态载入Groovy类,创建接口实例,调用接口中定义的方法
import groovy.lang.GroovyClassLoader;
import java.io.File;
public class InvokeGroovy {
public static void main(String[] args) {
ClassLoader cl = new InvokeGroovy().getClass().getClassLoader();
GroovyClassLoader groovyCl = new GroovyClassLoader(cl);
try {
Class groovyClass = groovyCl.parseClass(new File("src/Foo.groovy"));
IFoo foo = (IFoo) groovyClass.newInstance();
System.out.println(foo.run(new Integer(2)));
} catch (Exception e) {
e.printStackTrace();
}
}
}上面的方法是通过定义好接口来动态载入,如果没有接口怎么办...办法还是有的,那就是传说中的反射..Groovy也支持反射哦
2.通过反射,动态载入并使用Groovy类
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import java.io.File;
public class DynamicGroovy {
private GroovyObject groovyObject;
public Object getProperty(String name) {
return groovyObject.getProperty(name);
}
public Object invokeScriptMethod(String scriptName, String methodName, Object[] args) {
ClassLoader parent = getClass().getClassLoader();
GroovyClassLoader loader = new GroovyClassLoader(parent);
try {
Class groovyClass = loader.parseClass(new File(scriptName));
groovyObject = (GroovyObject) groovyClass
.newInstance();
return groovyObject.invokeMethod(methodName, args);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
DynamicGroovy dynamicGroovy = new DynamicGroovy();
Object[] params = {new Integer(2)};
Object result = dynamicGroovy.invokeScriptMethod("src/Foo.groovy", "run", params);
System.out.println(result);
System.out.println(dynamicGroovy.getProperty("x"));
}
}3.动态的载入Groovy脚本
动态载入脚本就更简单了,因为Groovy提供了一个方法evaluate,,和javascript的eval很像吧:
import groovy.lang.Binding;
import groovy.lang.GroovyShell;public class TestEval {
public Object doit() {
Binding bb = new Binding();
bb.setVariable("test", "hello world!");
GroovyShell gs = new GroovyShell(bb);
return gs.evaluate("println test");
}/**
* @param args
*/
public static void main(String[] args) {
TestEval te = new TestEval();
te.doit();}
}
简单吧,通过evaluate一个字符串就行了,evaluate还支持脚本文件和类文件哦....功能很强大的.
-
Groovy与流行框架的集成
1.与Spring的集成
现在Spring的核心包就提供了与Groovy的集成了,,很好,很强大,这样就可以显示业务逻辑的动态改变了
由于Groovy的代码中也有描述Java代码的机制,因此两者合用非常容易
Spring Bean:
代码
class="org.springframework.beans.factory.groovy.GroovyFactory">
20
下面是groovy的例子:代码
factory-bean="groovyScriptFactory"
factory-method="create">
SimpleHello.groovy
groovy文件:代码
package org.springframework.beans.factory.groovy;
class Test implements Hello {
String sayHello() {
"hello world"
}
}2.与webwork的集成
在WebWork2中,可以使用Groovy实现Action类来简化代码,提高编码效率
例子:
package web
import java.util.Date
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
import com.opensymphony.xwork.ActionSupport
class GroovyAction extends ActionSupport {
protected final Log logger = LogFactory.getLog(getClass())
private String now
String execute() {
now = "${new Date()}"
logger.info("returning view with ${now}")
"success"
}
void setNow(String now) {
this.now = now
}
String getNow() {
now
}
}
上面的Action类是Groovy类,同样扩展ActionSupport,这里要注意:execute()方法没有throws Exception语句,这是因为目前的Groovy还没有这个Java特性,这需要在以后的版本中增加;如果添加,编译会报错
execute()方法返回时,不要使用类似SUCCESS的常量,而是用对应的值(如"success");如果使用SUCCESS,Groovy会把它解析成类的属性,抛异常
当然,在/WEB-INF/lib目录下需要包含运行以依赖的jar文件:Groovy和ASM.
首先强烈遣责water ye同学不负责任的行为,那家伙在blog上贴了一段spring 2.0m2的test代码就了事,居然不测试一下,结果俺的spring groovy test代码折腾半天才过去。
测试代码俺就不贴了,spring的配置就够了1 <? xml version="1.0" encoding="GBK" ?>
2 <! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
3 "http://www.springframework.org/dtd/spring-beans.dtd" >
4 < beans >
5 < bean class ="org.springframework.scripting.support.ScriptFactoryPostProcessor" />
6 < bean id ="inlineMessenger" class ="org.springframework.scripting.groovy.GroovyScriptFactory" >
7 < constructor-arg >
8 < value > inline:
9 package spring.groovy;
10
11 class GroovyInlineMessenger implements Messenger{
12 void sayHello(){
13 System.err.println("Hello");
14 }
15 }
16 </ value >
17 </ constructor-arg >
18 </ bean >
19 < bean id ="messenger" class ="org.springframework.scripting.groovy.GroovyScriptFactory" >
20 < constructor-arg value ="classpath:spring/groovy/GroovyMessenger.groovy" />
21 < property name ="message" value ="Hello World!" />
22 </ bean >
23 </ beans >
1、第5行的bean定义一定要有,估计是提前编译groovy脚本的(具体的可能啃一下源码就明白了)。
2、inlineMessenger这个bean的定义,inline一定要紧跟着<value>写,我为了美观,弄成下面两种写法都没过去。1 < bean id ="inlineMessenger" class ="org.springframework.scripting.groovy.GroovyScriptFactory" >
2 < constructor-arg >
3 < value >
4 inline:
5 package spring.groovy;
6
7 class GroovyInlineMessenger implements Messenger{
8 void sayHello(){
9 System.err.println("Hello");
10 }
11 }
12 </ value >
13 </ constructor-arg >
14 </ bean >1 < bean id ="inlineMessenger" class ="org.springframework.scripting.groovy.GroovyScriptFactory" >
2 < constructor-arg >
3 < value >
4 <![CDATA[ inline:
5 package spring.groovy;
6
7 class GroovyInlineMessenger implements Messenger{
8 void sayHello(){
9 System.err.println("Hello");
10 }
11 } ]]>
12 </ value >
13 </ constructor-arg >
14 </ bean >写成这样倒是过的
1 < bean id ="inlineMessenger" class ="org.springframework.scripting.groovy.GroovyScriptFactory" >
2 < constructor-arg >
3 < value > <![CDATA[ inline:
4 package spring.groovy;
5
6 class GroovyInlineMessenger implements Messenger{
7 void sayHello(){
8 System.err.println("Hello");
9 }
10 } ]]>
11 </ value >
12 </ constructor-arg >
13 </ bean >俺平时习惯让myeclipse对xml进行格式化,照这么看来,估计一不小心,按个ctrl+shift+F,好端端的spring groovy代码就过不去了,然后就慢慢找问题吧。