Groovy探索之MOP 十四 对Java类使用Groovy语言的MOP
??????? Groovy探索之MOP 十四 对Java类使用Groovy语言的MOP ? ? ? 既然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,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 ? ? 最后一个方法是我们可以通过在“MetaClassRegistry”类上注册一个“MetaClass”对象来使用Java类拥有“MetaClass”属性,从而获得MOP能力。 首先,我们需要自定义一个“MetaClass”类,如下: //(Groovy代码) class FooDelegatingMetaClass extends groovy.lang.DelegatingMetaClass{ ??? ??? FooDelegatingMetaClass(final Class aclass) ??? { ?????? super(aclass); ?????? initialize() ??? } ??? ??? public Object invokeMethod(Object a_object,Object[] a_arguments) ??? { ?????? def result ?????? if(a_methodName == 'test') ?????? { ?????????? result = 'test' ?????? } ?????? else ?????? { ?????????? result = "${super.invokeMethod(a_object,a_methodName,a_arguments)}" ?????? } ?????? ?????? result ?????? ??? } ? } ? 这也和其他的自定义“MetaClass”类一样,不同的是我们在对Java类使用的时候,需要在“MetaClassRegistry”类上注册。如下: ? ??? ? //(Groovy代码) ??? ? def myMetaClass = new FooDelegatingMetaClass(Foo.class) ??? ? def invoker = InvokerHelper.instance ??? ??invoker.metaRegistry.setMetaClass(Foo.class,myMetaClass) ? ? 注册完了,我们就可以使用了: ? ??? ? def foo = new Foo() ??? ? ??? ? println foo.test() ??? ? 一切都很简单,需要注意的是,在注册的时候,需要引入如下的类: ? import org.codehaus.groovy.runtime.InvokerHelper ? ? 最后,我们运行上面的测试代码,得到如下的结果: test (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |