假设我们有一个 groovy 类 Whatever,这个类有方法 outer 和 inner,它们互相调用,并且我们故意丢失了调用顺序,我们希望得到像下面这样的运行时的方法调用过程:[code]before method ‘outer’
before method ‘inner’
after method ‘inner’
after method ‘outer’
[/code]这证实了在 outer 方法中调用了 inner 方法。
由于这是一个 GroovyObject 对象,我们能够覆盖 invokeMethod 方法,为了保证我们能够拦截定义的所有方法,我们需要实现 GroovyInterceptable 接口,这是一个标记接口,没有任何方法需要实现。
在 invokeMethod 方法内部,我们在执行方法调用前后写跟踪日志,为了日志的可观察性我们保留了缩进,跟踪输出默认为 System.out 或者一个给定的 Writer,这样容易进行测试,我们通过提供一个 writer 属性来达到这个目标。
为了使我们的代码更清晰,我们将所有的跟踪函数在父类 Traceable 中,列表 7.25显示了最终解决方案。
当中转方法调用的时候重要的是不能进入一个无限循环中,在使用同一种方式拦截方法
调用的时 候(因此 在图 7.3 中进入 了同一 列)这 是不可 避免的, 我们在 (1)调用
invokeMethod 方法强制进入了最左边的列。
在(2)我们使用了 groovy 便利的 StringBuffeWriter 来进行输出,然后输出到System.out,使用新的 Whatever 不需要参数。
在(2)开始整个执行过程,我们也断言我们将获取到适当的结果。 不幸的是,这个解决方案有限制,首先,它仅仅工作在 GroovyObject 对象上,不能是任意的 java 类,第二,如果检查的类已经继承了别的类,那么它是不工作的。
回忆图 7.3,我们需要通过替换在 MetaClassRegistry 中的 MetaClass 来跟踪所以的日志,这样的一个类已经在 groovy 代码库中:ProxyMetaClass。
这个类担当一个已经存在的 Meta 装饰,并且通过使用一个 Interceptor 来增加拦截能力(参考 groovy javadoc 的 groovy.lang.Interceptor 文档),幸运的是,已经存在了一个 TracingInterceptor,列表 7.26 显示了我们怎样在 Whatever 中使用这个类。
注意这个解决方案在从 groovy 中调用 java 类的时候也可用。
对于 GroovyObject 对象可以不通过 MetaClassRegistry 进行调用,你可以使用use 方法来保证它的工作:[code]proxy.use(traceMe){
// call methods on traceMe
}
[/code]Interceptor 和 ProxyMetaClass 对调试是有用的,但是仅仅适用简单任务。
注意:在应用大范围的改变到 MetaClassRegistry 的时候要当心,这可能导致代码
产生看起来与它们无关的潜在错误。小心的使用切面,这样可以避免太多切面造成的痛苦。
这就是 Groovy 的元能力,他是有许多魔术的魔术师,并且你自己也可以成为一个魔
术师。
MOP 使 Groovy 成为一门动态语言,它是 groovy 带给 java 平台许多发明的基础,这本书的其余部分将展示更重要的部分:建造者、标记、持久化、分布式编程、基于测试目的的透明模拟和存根,建立在已经存在的框架上的动态 API 类型,如用于 Windows Scripting 的 Scriptom 或者通过 Hibernate 建立的 ORM。
这些动态特性使得在 java 平台建立像 Grails 这样的框架成为可能。
Groovy 通常被认为是 JVM 的一个脚本语言,但它的 java 的脚步能力不是最根本的区别特征,MOP 和结果动态提升使 Groovy 比其他语言更高一等。

