Groovy 方法调用和拦截

Groovy 生成 java 字节码,这样每一个方法的处理都遵循下列机制之一:

1、 类自己实现 invokeMethod 的方法(这也许被代理到 MetaClass);

2、 它自己的 MetaClass,通过 getMetaClass().invokeMethod()进行调用;

3、 在 MetaClassRegistry 中注册的该类型的 MetaClass。

图groovy 中三种不同类型的方法(根据被调用对象的类型和方法是否可以)调用逻辑进行调用的逻辑显示在图 7.3 中,在图中的每个数字对对应在前面的数字列表中的项。

每个方法的调用时复杂的决策,当然很多时候你不需要考虑这些,你不应该在每个方法调用的时候都考虑这些,毕竟,groovy 已经使这些事情变得容易了一些,不管怎样,明白这些细节是有价值的,这样在复杂的情况下你总是可以正确的工作,它也为你在你的类中增加动态行为提供了各种可能。

包括了下面的可能性:

 你能够使用 aspects 进行方法调用的拦截,如日志跟踪、应用安全限制,强制事务控制等等。

 你能够中转调用别的方法,例如,一个包装类能中转所有的方法调用到被包装的对象上。

顺便说一下:闭包也是这样做的,它将方法调用代理给它的 delegate。

 可以假装执行一个方法,这样可以应用一些特殊逻辑,例如,一个 Html 类可以假装有一个方法 body,当调用 body 方法的时候执行 print(‘body’)。

顺便说一下,builder 就是这样做的,他们假装有相应的方法来定义嵌套产品结构。

调用逻辑有多种方式来实现拦截、中转或者伪装方法:

 实现/覆盖在 GroovyObject 中的 invokeMethod 方法来伪装或者中转方法调用(通常你定义的所有方法仍然被调用);

 实现 / 覆盖在 GroovyObject 中的 invokeMethod 方法,并且也实现GroovyInterceptable 接口来增加方法的拦截调用代码。

 提供一个 MetaClass 的 实 现 类, 并 且 在 目 标 GroovyObject 对象上调用 setMetaClass;

 提供一个 MetaClass 的实现类,并且在 MetaClassRegistry 中为所有的目标类(Groovy 和 java 类)进行注册,这种方案通过 ProxyMetaClass 进行支持。

一般的说,覆盖/实现 invokeMethod 方法意味着覆盖点方法操作符。