前篇: 在Spring+Hibernate框架下,用动态语言写业务类
1.虽然只是语法糖,但忽然间一整吨语法糖摆在面前还是很让人感动的。
Groovy完全兼容Java语法,但又提供糖糖选择的方式感觉很贴心。
先贴一段DAO类的片断,然后逐条解释:
package com.itorgan.myappfuse.dao;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
public class CustomerDAOGroovy extends HibernateDaoSupport
{
public insert(customer)
{
getHibernateTemplate().save(customer);
}
public List getAllValid(sortColumn)
{
hql = "from Customer customer
where customer.status='valid'
order by ${sortColumn}";
query = getSession().createQuery(hql);
return query.list();
}
public boolean isUnique(customer, uniqueColumnNames)
{
params = [];
hql = "select count(*) from Customer customer where ";
first = true;
uniqueColumnNames.tokenize(",").each
{
if (!first)
hql += " or ";
else
first = false;
hql+="customer.${it}=?";
params << customer.getAt(it);
}
result = getHibernateTemplate().find(hql,params.toArray());
return ( result.get(0) == 0);
}
}
1.动态类型,参见insert(customer)函数
动态类型在Framework型项目中非常重要,多少设计模式呕心沥血,就是为了和这个类型搏斗。
2.强大的String类,参见getAllValid(orderColumn)函数中hql的定义
a.hql 可以多行,不用写N多"和+ , 写sql时特别方便。
b.可以直接在String中嵌入EL, "orderBy ${sortColumn}",也是省了好多"和+号。
3.为String等基础类扩展了tokenize()等简便方法,参见最后一个函数
//原来StringTokenizer类的功能被简单的集成到String类中了
names.tokenize(",").each{......}
其他的扩展见Groovy-JDK
4. 集合与循环的语法,参见最后一个函数
for (car in cars) { println car }
或者
car.each{print it}
5.内建的反射语法,参见最后一个函数
customer.getAt("name") //得到属性name,
customer.invokeMethod("someFunction") //调用方法someFunction
从此不再需要Apache BeanUtils了。
6.运算符冲载,参见最后一个函数
//向数组添加对象
params << customer.getAt(it);
还有如C++的向String,InputStream添加对象.
其他没有反映在这里的语法糖:
7.简化的Bean定义与赋值
//自动生成Getter和Setter
class Customer
{
Integer id;
String name;
}
//简便的对象赋值
customer = new Customer(id:1, name:"calvin");
customer2 = new CUstomer(id:2);
8.内置的XML语法,和Fremarker类似。
JDom和Dom4j可惜安息了
book = new XmlSlurper().parseText("<book writer='calvin'><title>D</title></book>")
println book.title;
println book[@writer];
println book.children.size();
9.closure-闭包
我觉得就如函数指针,所有的动态语言好像都觉得他很重要
myClosure = { println "Hello, world!" };
myClosure.call();
10.在String的EL中,避免Null Point Exception
//用"->"而不是".",可以避免NPE.
Customer me = null;
s= "${me->name}";
2.编译
ant的build.xml:
<path id="groovy.classpath">
<pathelement path="${basedir}/ROOT/WEB-INF/classes/"/>
<fileset dir="${basedir}/ROOT/WEB-INF/lib">
<include name="*.jar"/>
</fileset>
</path>
<taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc">
<classpath refid="groovy.classpath"/>
</taskdef>
<target name="groovy">
<groovyc destdir="${project.basedir}/ROOT/WEB-INF/classes" srcdir="${project.basedir}/src"
listfiles="true">
<classpath refid="groovy.classpath"/>
</groovyc>
</target>
3.Groovy现状
Groovy完成了10个Beta版本后,开始转向符合JSR的版本开发.本来预计每月出一个版本,今年夏天出正式版的.但目前JSR-2已经晚了一个月还没发布.而且看它的 JIRA,还有很多任务没有完成.
JSR2主要是本着人有我有的精神,抄袭Ruby的Module和Maxin(混入), 实现多重继承.
IDE方面, idea和Eclipse都有语法变色的简陋插件,而真正的基于 IDEA5.0的插件还没写好.
4.如何用Java实现动态语言
把GroovyC编译出来的class文件再用jad反编译,可以看到如何用Java去实现一门动态语言。
主要是多了一个MetaClass,不断的反射反射,运行时还非常依赖asm
最简单的例子:
Groovy文件:
public class Customer
{
private String id;
}
编译出来的Java文件
public class Customer implements GroovyObject
{
private String id;
transient MetaClass metaClass;
public Customer()
{
Object obj = ScriptBytecodeAdapter.invokeStaticMethod("org.codehaus.groovy.runtime.ScriptBytecodeAdapter", "getMetaClass", this);
metaclass metaclass = (MetaClass)ScriptBytecodeAdapter.asType(obj, groovy.lang.MetaClass.class);
}
public Object invokeMethod(String s, Object obj)
{...}
public Object getProperty(String s)
{....}
5.参考资料
Groovy网站的文档不多
2.Open Java Project的blog,Groovy文档的中文版