既然Groovy语言是Java语言的扩展,那么我们在使用Groovy语言的时候,就很难与Java语言真正脱得了干系,那怕我们是在做一个纯Groovy语言的项目,如Grails项目。我们可能在Groovy代码中会用到遗留的Java类和包;也可能是为了性能的原因,我们不得不在Groovy语言中使用到Java类;等等。
如果我们要对于Java类使用Groovy语言的MOP,比如我们想给一个Java类的对象在运行期内添加一个方法。那么我们该怎么办呢?
比如,我们有如下的一个Java类:
//(Java代码)
public class Foo {
public String foo()
{
return "foo";
}
}
我们就可以使用如下的方法在运行期内给它的对象添加一个方法:
//(Groovy代码)
ExpandoMetaClass emc = new ExpandoMetaClass( Foo, false )
emc.hello = {"hello,world!"}
emc.initialize()
上面的代码用来初始化一个“ExpandoMetaClass”对象,然后添加一个方法,然后将这个对象实例化;这些都跟给Groovy对象在运行期内添加一个方法的过程一样,没有什么好多说的。
接下来,我们的代码就和对Groovy对象的操作不一样了,要使用“Proxy”类来包装我们的Java类对象,如下:
def foo = new groovy.util.Proxy().wrap(new Foo())
然后就是给这个对象赋值上面的“ExpandoMetaClass”对象:
foo.setMetaClass(emc)
最后,我们就可以测试了:
println foo.hello()
运行结果为:
hello,world!
同样,对于我们上面的Java类,我们也可以使用我们的自定义拦截器来拦截它的动作:
//(Groovy代码)
class FooInterceptor implements Interceptor{
Object beforeInvoke(Object a_object, String a_methodName, Object[] a_arguments)
{
if(a_methodName == 'foo')
{
println 'before invoking function foo'
}
}
boolean doInvoke()
{
return true
}
Object afterInvoke(Object a_object, String a_methodName, Object[] a_arguments, Object
a_result)
{
a_result
}
}
这个拦截器跟我们拦截Groovy类的自定义拦截器是一模一样的。使用这个拦截器的方法也是一样的:
//(Groovy代码)
def proxy = ProxyMetaClass.getInstance(Foo.class);
proxy.interceptor = new FooInterceptor()
proxy.use {
def foo = new Foo()
println foo.foo()
}
运行结果为:
before invoking function foo
foo