Groovy探索之MOP 十三 Interceptor 三(2)
其实,阻止拦截的使用像在《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
的确起到了阻止拦截的效果。