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

Groovy探索之MOP 十三 Interceptor 三(1)

編輯:Groovy

本篇的“Interceptor”,主要是來說說攔截器的阻止攔截的問題,這個問題是我們自定義攔截器時經常要遇到的挑戰之一。

與阻止攔截很近的一個意思是不攔截,即我們可以攔截某個方法,但我們不對攔截做任何實質性的動作,即我們簡單的將攔截的動作放行。這是一種被動的不攔截行為。而我們的阻止攔截卻更為主動一些,即不讓攔截器攔截到某個方法。

下面,我們將分別就放行攔截和阻止攔截來舉例說明。

首先,我們還是設計一個需要被攔截的類來:

class Foo {
def foo()
{
println 'foo'
}
def bar()
{
println 'bar'
}
}

假設我們不想攔截“bar”方法,只想攔截“foo”方法,則我們可以這樣設計攔截器:

class NoBarInterceptor implements Interceptor{
Object beforeInvoke(Object object, String methodName, Object[] arguments){
if(methodName == 'foo')
{
println 'interceptor the function: foo'
}
}
boolean doInvoke(){ true }
Object afterInvoke(Object object, String methodName, Object[] arguments,
Object result){
result
}
}

在代碼中,我們只攔截了方法名為“foo”的方法,對其他方法則未做處理,即放行了。我們來寫一點測試代碼:

def proxy= ProxyMetaClass.getInstance( Foo )
proxy.interceptor= new NoBarInterceptor()
proxy.use{
def f= new Foo()
f.foo()
f.bar()
}

運行結果為:

interceptor the function: foo
foo
bar

當然了,如果我們想更加主動的確定對哪些方法放行,則可以這樣設計我們的攔截器:

class NoMethodInterceptor implements Interceptor{
def methods
Object beforeInvoke(Object object, String methodName, Object[] arguments){
if(!(methodName in this.methods))
{
println "before invoking $methodName"
}
null
}
boolean doInvoke(){ true }
Object afterInvoke(Object object, String methodName, Object[] arguments,
Object result){
result
}
}

在上面的代碼中,使用if判斷語句對需要攔截的方法做了限制,使得該攔截器不能攔截我們給定的某些方法。一切的邏輯都很簡單,所以測試代碼在這裡也不再給出了,你們可以自己寫點測試代碼來測試一下。

而阻止攔截的概念則更強一些,即我們強烈的要求對某些方法不做攔截,這樣使得攔截器不去攔截它們。比如我們有如下的一個需要被攔截的類:

class Hello {
def hello(name)
{
"hello,$name"
}
}

我們需要攔截“hello”方法,並在前面打印一些log信息,我們可能會這樣寫這個攔截器:

class StopInterceptor implements Interceptor{
Object beforeInvoke(Object object, String methodName, Object[] arguments){

}
boolean doInvoke(){ true }
Object afterInvoke(Object object, String methodName, Object[] arguments,
Object result){
if(methodName == 'hello')
{
result = new Hello().hello('log')+'\n'+result
}
result
}
}

我們在攔截器裡攔截了“hello”方法,並且在它的返回結果使用“hello”方法添加了一些log記錄。現在我們可以寫代碼來測試它:

def proxy= ProxyMetaClass.getInstance( Hello )
proxy.interceptor= new StopInterceptor()
proxy.use{
def hello = new Hello()
println hello.hello('World')
}

運行結果卻發現了Exception:

Exception in thread "main" java.lang.StackOverflowError

並且是堆棧溢出。這是因為下面的語句:

if(methodName == 'hello')
{
result = new Hello().hello('log')+'\n'+result
}

我們在攔截器裡又調用了“hello”方法,這個“hello”方法又被攔截器攔截,然後又調用“hello”方法,然後又被攔截,…這樣就進入了死循環,導致了堆棧溢出。

那麼,我們該怎麼解決上面的問題呢?當然是希望攔截器裡的“hello”方法不要再被攔截器攔截,解決方法很簡單,就是在不希望被攔截的方法前面加上“&”標識符,如上面的語句可以修改為:

if(methodName == 'hello')
{
result = new Hello().&hello('log')+'\n'+result
}

這樣,我們再運行上面的測試代碼,結果為:

hello,log
hello,World

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