使用 methodMissing & propertyMissing
自从版本1.5 ,Groovy开始支持 "methodMissing",熟悉MetaClass机制后,从这个名字不难看出这个是用来干什么的,就是当找不到某个方法的时候,这个方法就会被调用。
一般说来,既然已经有invokeMethod了,那么为什么还要”多此一举“呢?
下面是使用这个特性的一些准则:
这个特性只发生在常规方法分配失败之后,执行代价是相对比较高的;
相对于每次都调用invokeMethod来说,这个特性只发生在常规调用失败之后,有效利用,总体上可以提高执行的性能;
如何有效利用呢,常见的做法是,使用这个特性来执行动态方法的注册,即当这个特性被第一次触发的时候,执行某些逻辑,保证下次发生同样的调用时,能够转换成常规调用,这样,就实现了第一次调用时,才支持方法这样一个非常好的效果。
看下面这个例子:
class GORM {
def dynamicMethods = [...] // an array of dynamic methods that use regex
def methodMissing(String name, args) {
//查找是否支持这个方法
def method = dynamicMethods.find { it.match(name) }
if(method) {
//如果支持,动态添加这个方法的定义
GORM.metaClass."$name" = { Object[] varArgs ->
method.invoke(delegate, name, varArgs)
}
//实现第一次调用,下次调用,不会再进入methodMessing方法体
return method.invoke(delegate,name, args)
}
else throw new MissingMethodException(name, delegate, args)
}
}
对于 propertyMissing,和methodMessing是类似了,也不用解释过多,看例子就好了。
class Foo {
def propertyMissing(String name) { name }
}
def f = new Foo()
assertEquals "boo", f.boo
下面这个例子更体现propertyMissing的价值。
class Foo {
def storage = [:]
def propertyMissing(String name, value) { storage[name] = value }
def propertyMissing(String name) { storage[name] }
}
def f = new Foo()
f.foo = "bar"
assertEquals "bar", f.foo