Groovy探索之MOP 十一 运行期内覆盖invokeMethod
?Groovy探索之MOP 十一 运行期内覆盖invokeMethod ? ? ? ?????? 我们很早就会使用Groovy语言的hook,即"invokeMethod"方法和其他的几个方法。我们会在一个类中实现"invokeMethod"方法,用来分派所有的或部分的在运行期内调用的该类实例的方法。这些我们在《Groovy探索之MOP 一 invokeMethod和methodMissing方法》已经详细的谈到过。 现在,我们已经深入的接触到了Groovy语言的MetaClass,更是也到处使用到了ExpandoMetaClass。我们都已经知道,ExpandoMetaClass的灵活性,不是hook能够比拟的。我们就想,既然使用ExpandoMetaClass能够在运行期内给一个类增加方法,那么,我们是否也可以在运行期内增加hook方法呢? 我们可以回答,是。还是先来看一个简单的例子吧! 我们还是有这么一个简单的类: ? class Foo { ??? def foo() ??? { ?????? 'foo' ??? } ??? ? } ? 我们现在尝试着在运行期内增加"invokeMethod"方法: ??? ? ??? ? Foo.metaClass.invokeMethod = { ?????????? ? String name,args1 -> ????????????? 'test' ?????????? ? ? ??? ? } ? 接着,我们来测试这个运行期内增加的"invokeMethod"方法: ? ??? ? def foo = new Foo() ??? ? ??? ? println foo.foo() ??? ? ??? ? println foo.test() ??? ? 运行结果为: test test ? ? 可以看出,我们在运行期内增加的"invokeMethod"方法拦截了Foo类的实例的所有的方法。 当然,如果我们想把"invokeMethod"方法拦截的方法中,已经存在于Foo类的方法,如"foo",交给Foo类本身的方法来处理。那么,我们就可以如下实现"invokeMethod"方法: ? ??? ? Foo.metaClass.invokeMethod = { ?????????? ? String name,args1 -> ?????????? ? ? def m = Foo.metaClass.getMetaMethod(name,args1) ?????????? ? ? def result ?????????? ? ? if(m) ?????????? ? ????? result = m.invoke(delegate,args1) ?????????? ? ? else ?????????? ? ????? result = 'test' ?????????? ? ? result ? ??? ? } ? ? 我们再运行上面的测试代码,就会得到如下的结果: foo test ? 现在,我们来定义几个名词,我们把类本身实现的"invokeMethod"方法称为对象的"invokeMethod"方法,而把在运行期内通过ExpandoMetaClass增加的"invokeMethod"方法称为metaClass的"invokeMethod"方法。 现在的问题是,如果一个对象,同时实行了对象的"invokeMethod"方法和metaClass的"invokeMethod"方法,那么该调用谁? 你肯定会说,这个问题很简单啊,我们来做一个简单的测试不就知道了。好,现在,我们先来看看这个简单的测试。 首先,我们把上面的Foo类增加"invokeMethod"方法: ? class Foo { ??? def foo() ??? { ?????? 'foo' ??? } ??? ??? def invokeMethod(String name,args) ??? { ?????? 'invoke'?? ??? } ? } ? ? 同时,我们在运行期内也增加该方法,然后做测试: ? ??? ? Foo.metaClass.invokeMethod = { ?????????? ? String name,args1) ?????????? ? ? else ?????????? ? ????? result = 'test' ?????????? ? ? result ? ??? ? } ??? ? ??? ? def foo = new Foo() ??? ? ??? ? println foo.foo() ??? ? ??? ? println foo.test() ??? ? 运行的结果为: foo test ? ? 从结果可以看出,metaClass的"invokeMethod"方法覆盖了对象的"invokeMethod"方法。即如果存在metaClass的"invokeMethod"方法,则优先调用metaClass的"invokeMethod"方法,而不管对象的"invokeMethod"方法是否存在。 最后,我们还定义一个名词:GroovyInterceptable的"invokeMethod"方法。这个名词其实我们在《Groovy探索之MOP 一 invokeMethod和methodMissing方法》也接触过,就是一个类如果实现了"GroovyInterceptable"接口,那么它的类本身的"invokeMethod"方法,就是GroovyInterceptable的"invokeMethod"方法。如下所示: ? class Foo implements GroovyInterceptable{ ? ??? def foo() ??? { ?????? 'foo' ??? } ??? ??? def invokeMethod(String name,args) ??? { ?????? 'invoke'?? ??? } ? } ? 现在,我们需要知道,如果一个对象的GroovyInterceptable的"invokeMethod"方法和metaClass的"invokeMethod"方法都存在,那么又是如何调用的? 还是对上面已经实现了"GroovyInterceptable"接口的Foo类如下测试: ? ??? ? Foo.metaClass.invokeMethod = { ?????????? ? String name,args1) ?????????? ? ? else ?????????? ? ????? result = 'test' ?????????? ? ? result ? ??? ? } ??? ? ??? ? def foo = new Foo() ??? ? ??? ? println foo.foo() ??? ? ??? ? println foo.test() ??? ? 运行结果为: invoke invoke ? ? 从运行结果可以看出,GroovyInterceptable的"invokeMethod"方法是优先于metaClass的"invokeMethod"方法的调用的;或者说,如果一个对象同时存在GroovyInterceptable的"invokeMethod"方法和metaClass的"invokeMethod"方法,那么系统将调用GroovyInterceptable的"invokeMethod"方法,而不管metaClass的"invokeMethod"方法。 最后,我们来做一个总结吧。对于一个对象的方法调用,如果该对象的类实现了"GroovyInterceptable"接口,那么,系统将调用GroovyInterceptable的"invokeMethod"方法;否则,系统将调用metaClass的"invokeMethod"方法;如果该对象没有实现metaClass的"invokeMethod"方法,那么系统将调用对象的"invokeMethod"方法。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |