加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Groovy探索之MOP 十一 运行期内覆盖invokeMethod

发布时间:2020-12-14 17:08:38 所属栏目:大数据 来源:网络整理
导读:? Groovy探索之MOP 十一 运行期内覆盖invokeMethod ? ? ? ?????? 我们很早就会使用Groovy语言的hook,即"invokeMethod"方法和其他的几个方法。我们会在一个类中实现"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"方法。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读