其實,阻止攔截的使用像在《Groovy探索之MOP 十三 Interceptor 三(1)》中的最後一個例子那像的使用並不多,更多的是在使用攔截器的客戶那裡決定是否使用攔截器。還是上一篇的那個例子:
class Hello {
def hello(name)
{
"hello,$name"
}
}
我們現在明確的把類中所有的方法進行攔截,攔截器如下:
class AllInterceptor implements Interceptor{
Object beforeInvoke(Object object, String methodName, Object[] arguments){
println "the function-$methodName is intercepted"
}
boolean doInvoke(){ true }
Object afterInvoke(Object object, String methodName, Object[] arguments,
Object result){
result
}
}
在上面的攔截器中,我們在“beforeInvoke”方法中攔截了被攔截對象中的所有方法,打印出哪個方法被攔截的提示出來。
比如,我們做如下的測試代碼:
def proxy= ProxyMetaClass.getInstance( Hello )
proxy.interceptor= new AllInterceptor()
proxy.use{
def hello = new Hello()
hello.hello('World')
}
運行結果為:
the function-ctor is intercepted
the function-hello is intercepted
表示已經有了兩個方法被攔截。現在,我們的客戶端不想攔截“hello”方法,在這裡我們就可以使用阻止攔截了:
def proxy= ProxyMetaClass.getInstance( Hello )
proxy.interceptor= new AllInterceptor()
proxy.use{
def hello = new Hello()
hello.&hello('World')
}
運行結果為:
the function-ctor is intercepted
這樣就沒有對“hello”方法進行攔截。
我們還是需要回憶一下上一篇中遇到的嵌套攔截的問題,即在攔截器中又調用了需要被攔截的那個方法,形成了嵌套攔截的問題。我們在上一篇中的解決方法是使用“&”標識符進行阻止攔截。使用“&”標識符畢竟只能阻止少量的方法進行嵌套攔截,在實際的使用中不是很方便,為了解決這個問題,我們也有一個一勞永逸的解決辦法。即我們可以創建一個阻止嵌套攔截器類,讓繼承它的所有攔截器具備有阻止嵌套攔截的能力。
這個基類如下:
abstract class UninterceptedInterceptor implements Interceptor{
def proxy= null
abstract Object doBefore( Object object, String methodName,
Object[] arguments )
public Object beforeInvoke( Object object, String methodName,
Object[] arguments ){
proxy.interceptor= null
def result
try{
result= doBefore(object, methodName, arguments)
}catch(Exception e){
throw e
}finally{
proxy.interceptor= this
}
result
}
abstract boolean doInvoke()
abstract Object doAfter( Object object, String methodName, Object[] arguments,
Object result )
public Object afterInvoke( Object object, String methodName,
Object[] arguments, Object result ){
proxy.interceptor= null
try{
result= doAfter(object, methodName, arguments, result)
}catch(Exception e){
throw e
}finally{
proxy.interceptor= this
}
result
}
}
這個基類很簡單,可以放到我們的工具包裡去。我們只看“beforeInvoke”方法,思想就是,我們的攔截動作都放在“doBefore”方法裡,同時,在執行“doBefore”方法的時候,我們使用如下的語句將攔截器去掉:
proxy.interceptor= null
當“doBefore”方法完了以後,我們再把攔截器加上,使用下面的語句:
proxy.interceptor= this
這樣,我們需要進行嵌套攔截的類就繼承該類,如下:
class MyInterceptor extends UninterceptedInterceptor{
Object doBefore( Object object, String methodName,
Object[] arguments )
{
}
boolean doInvoke()
{
true
}
Object doAfter( Object object, String methodName, Object[] arguments,
Object result )
{
if(methodName == 'hello')
{
result = new Hello().hello('log')+'\n'+result
}
result
}
}
這個類就更簡單了,在它裡面進行了攔截方法的嵌套調用,形如下面的語句:
if(methodName == 'hello')
{
result = new Hello().hello('log')+'\n'+result
}
攔截了“hello”方法,卻在裡面又進行“hello”方法的調用,一個很明顯的嵌套調用。
最後,我們來寫點代碼測試這個阻止攔截的攔截器:
def proxy= ProxyMetaClass.getInstance( Hello )
proxy.interceptor = new MyInterceptor()
proxy.interceptor.proxy = proxy
proxy.use{
def hello = new Hello()
println hello.hello('World')
}
這也和其他的測試代碼大致相似,唯一不同的是下面的語句:
proxy.interceptor.proxy = proxy
它需要我們給Interceptor對象的“proxy”屬性賦值,這在其他的測試代碼裡是沒有的。運行結果為:
hello,log
hello,World
的確起到了阻止攔截的效果。