程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Groovy >> Groovy探索之MOP 十四 對Java類使用Groovy語言的MOP

Groovy探索之MOP 十四 對Java類使用Groovy語言的MOP

編輯:Groovy

既然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

最後一個方法是我們可以通過在“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, String a_methodName, 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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved