- 浏览: 106283 次
- 性别:
- 来自: 上海
最新评论
-
toby941:
有办法不使用这种DGM机制么
Groovy深入探索——DGM调用优化 -
JohnnyJian:
joeytang 写道c = { -> println ...
Groovy学习笔记——在Groovy中调用Groovy脚本 -
joeytang:
c = { -> println a * 3 }
这 ...
Groovy学习笔记——在Groovy中调用Groovy脚本 -
JohnnyJian:
k不是什么下标,详细的话你还是看我另外一篇blog吧:http ...
Groovy学习笔记——用inject方法构造Map -
key232323:
汗。。。二维List原来也可以each{k, v这么用。。。
Groovy学习笔记——用inject方法构造Map
文章列表
Groovy中定义了不少ClassLoader,本文将介绍其中绝大多数Groovy脚本都会涉及到的,也是最主要的3个ClassLoader:RootLoader、GroovyClassLoader和GroovyClassLoader.InnerLoader。
注:以下分析的Groovy源代码来自Groovy 2.1.3。
Java的ClassLoader
顾名思义,Java的ClassLoader就是类的装载器,它使JVM可以动态的载入Java类,JVM并不需要知道从什么地方(本地文件、网络等)载入Java类,这些都由ClassLoader完成。
可以说,ClassLoader是Clas ...
在Python中提供了String format的操作符:
print '%s: %d' % ('one', 1)
在Java中则是通过String.format()方法实现:
System.out.println(String.format("%s: %d", "one", 1));
而在Groovy中,可以通过重载String的“%”操作符来实现类似Python风格的String format:
String.metaClass.mod = { List list ->
String.format(delegate, list as O ...
DGM调用优化是通过直接调用代替反射调用的方式来提高DGM方法的调用效率。
注:以下分析的Groovy源代码来自Groovy 1.8.0 rc4。
DGM
DGM其实是Groovy社区对DefaultGroovyMethods的简称,完整类名是org.codehaus.groovy.runtime.DefaultGroovyMethods。
DefaultGroovyMethods类中包含了Groovy为JDK的类添加的各种方法,如
[1, 2, 3].each { println it }
中的each方法就是Groovy为Object类添加的方法,用于遍历对象中的所有元素。在Object ...
本文介绍了Metaclass在Groovy中的存放方式,并对不同的情况(Per-class Metaclass、POGO Per-instance Metaclass和POJO Per-instance Metaclass)进行了分析。
注:以下分析的Groovy源代码来自Groovy 1.7.1,所有测试代码在Groovy 1.7.1下测试通过。
Metaclass
用过Groovy的程序员都或多或少、直接或间接的接触过Metaclass。简单来说,Metaclass就是Class的Class,Class定义了该类实例的行为,Metaclass则定义了该类及其实例的行为(http://en ...
假设我们有两个List,分别是a和b,a和b的长度相同,现在我们想把a的每个元素作为key,b中对应的元素作为value,构造一个Map,应该怎么写呢?
最直接的想法,先建立一个空的Map,然后往里面添加key-value对,代码如下(运用了我在http://johnnyjian.iteye.com/blog/271554中提到的同时迭代多个List的技巧):
def a = [1, 2, 3]
def b = [4, 5, 6]
def m = [:]
[a, b].transpose().each { k, v -> m += [(k): v] }
assert m == ...
Gmock是一个基于Groovy语言的mock框架。Gmock利用了Groovy语言的特性,提供了简洁可读的语法,并且用Gmock mock出来的对象可以在Java代码中使用,所以你可以使用Java编写代码而使用Groovy和Gmock编写测试。
本版本支持Groovy 1.6,但是实际上你需要使用Groovy 1.6.1,因为1.6.1修正了一些影响到Gmock的bug。
本版本利用了Groovy 1.6中的AST Transformation特性,提供了@WithGMock注解。如果你的测试不能(或不想)继承GMockTestCase,你可以使用这个注解:
@WithGMock
cl ...
Gmock是一个基于Groovy语言的mock框架。Gmock利用了Groovy语言的特性,提供了简洁可读的语法,并且用Gmock mock出来的对象可以在Java代码中使用,所以你可以使用Java编写代码而使用Groovy和Gmock编写测试。
本版本加入了以下特征:
1. 设定方法调用的严格顺序(strict ordering)。这是通过ordered闭包实现的。下面是一个被缓存的数据库的例子:
def database = mock()
def cache = mock()
ordered {
database.open()
cache.get("selec ...
Groovy 1.6引入了Call Site优化。Call Site优化实际上就是方法选择的cache。
方法选择
在静态语言(如Java)中,方法调用的绑定是在编译期完成的(不完全是这样,如虚函数,但总的来说,静态语言的方法调用是非常高效的)。而在动态语言(如Groovy)中,调用的方法是在运行时选择的。这也是造成动态语言比静态语言慢的重要原因之一。
举个例子来说明,譬如要调用“a.call(1)”。
如果是Java的话,在编译期就会选择好调用的方法,在这个例子中,就是选择a对象声明的类(注意,不是a对象真正的类,因为真正的类要到运行时才能知道)中,名字为call、有一个参数、参数类型为in ...
今天看到有人在Groovy的邮件列表上问Groovy能不能支持Ruby的case ... when表达式:
car = "Patriot"
manufacturer = case car
when "Focus": "Ford"
when "Navigator": "Lincoln"
when "Camry": "Toyota"
when "Civic": "Honda"
when ...
Gmock是一个基于Groovy语言的mock框架。Gmock利用了Groovy语言的特性,提供了简洁可读的语法,并且用Gmock mock出来的对象可以在Java代码中使用,所以你可以使用Java编写代码而使用Groovy和Gmock编写测试。
本版本添加了以下特性:
支持mock静态属性:
def mockLoader = mock(Loader)
mockLoader.static.name.returns('loader')
play {
assert Loader.name == 'loader'
}
引入with(mock)语法:
def mockLoader = ...
Gmock是一个基于Groovy语言的mock框架。与Java的各种mock框架相比,Gmock利用了Groovy语言的特性,提供了更精简、更可读的语法。而与Groovy的官方解决方案——MockFor类——相比,除了更精简和可读的语法之外,用Gmock mock出来的对象是可以在Java代码中使用的,所以你可以使用Java编写代码而使用Groovy和Gmock编写测试。
入门
首先,你的测试类需要继承org.gmock.GMockTestCase。然后,使用mock()方法创建mock对象,并且只需要直接在mock对象上调用方法即可设定预期行为:
def mockLoader = moc ...
假设我们有这样两个List:
def list1 = [1, 2, 3]
def list2 = [4, 5, 6]
我们需要检查是否第二个List的每个元素都比第一个List的对应元素大,最直接的想法是,迭代第一个List,然后通过下标访问第二个List:
def result = true
list1.eachWithIndex { n, i ->
if (n >= list2[i]) result = false
}
assert result
然而,这种方法不够直观,而且无法利用GDK本身提供的every方法。
实际上,我们可以利用Collection.tr ...
如果一个闭包被赋值给一个对象的属性(在脚本中,给一个没有定义过的变量赋值,实际上就是给这个脚本对象添加了一个属性),那么当需要对这个闭包进行递归调用的时候,可以直接使用这个属性的名字进行调用:
// 递归求n!
factorialProperty = { n ->
if (n == 0) return 1
n * factorialProperty(n - 1) // 使用这个属性的名字进行递归调用
}
assert 3628800 == factorialProperty(10)
如果把闭包赋值给一个局部变量,那么就必须先定义这个变量,再进行赋值:
def fa ...
在Closure中,方法的默认解析顺序是,先查看owner是否包含这个方法,如果没有的话再查看delegate是否有这个方法。实际的过程要比这个复杂,因为涉及到嵌套的Closure的情况,在这种情况下,还要考虑外围的Closure的delegate。在这里就不讨论嵌套Closure的情况了,有兴趣的可以查看ClosureMetaClass.invokeMethod方法的源代码。
我们可以通过Closure的setResolveStrategy方法改变这个解析的顺序:
class C {
def f() { println 'C.f' }
def closure = { f() ...
最近在研究Tapestry5,觉得不错,所以就尝试与Spring和Hibernate整合,并使用Groovy编写,实现简单的CRUD操作。
此整合的特点:
1. 因为使用了Groovy,所以并没有为Service和DAO层建立接口,一切都靠方法签名的约定
2. 尽量使用annotation,Spring中的依赖注入使用了JSR-250的@Resource,按照bean名字注入
3. 配置很少,我把需要修改的部分都集中在hibernate.cfg.xml中,即只有与数据库相关的部分有可能需要修改