原文链接:http://www.cnblogs.com/west-link/archive/2011/06/22/2086591.html
拦截器模式为我们提供了一种拦截方法调用或消息的途径,整个过程是自动的、透明的,下面是一个简单的拦截器示意图:
从图中可以看到,拦截器可以访问到方法调用的输入参数和返回结果,这样的话,拦截器能做的事儿就多啦,比如:
1、验证输入参数是否正确
2、偷偷地修改参数的值,例如参数类型的自动转换等
3、依赖注入
4、修改返回结果的内容、格式等
下面是一个包含我们要拦截的方法的类:
public
class
Action{
//
拦截器集合的迭代器
private
Iterator interceptors;
//
输入参数
private
Parameter param;
//
返回结果
private
Result result;
//
构造函数
public
Action(Parameter param);
//
这个方法是我们要拦截的(具体实现见下面)
public
Result invoke();
//
其他...
}
下面声明一个拦截器接口:
public
interface
Interceptor{
public
Result intercept(Action action); }
我们可能会想到以下的拦截方式:
//
先在方法调用之前拦截一下,可以处理输入参数
intercept(param);
//
调用方法
result
=
action.invoke(param);
//
在方法调用之后再拦截一下,可以处理返回结果
intercept(result);
这种方式的缺点是不能完全地控制方法的调用,比如不能跳过方法的调用而直接返回结果、不能更改所在对象内部的状态等。
下面的实现也能达到方法调用的前后拦截,并且有完全控制该对象的能力
public
Result invoke(){
if
( interceptors.hasNext() ){ Interceptor interceptor
=
interceptors.next(); result
=
interceptor.intercept(
this
); } }
下面我们举几个拦截的具体例子:
//
参数合法性验证拦截器
public
ParamInvalidator
implements
Interceptor{
public
Result intercept(Action action){ Paramemter param
=
action.getParam();
//
确保参数不为null
if
(param
==
null
){ addMessege(
"
param is null!
"
);
//
创建一个默认的参数对象
action.setParam(
new
Paramemter()); }
//
继续调用过程
return
action.invoke(); } }
一般来说,这类拦截器应该放在拦截器集合的最前面,所以,拦截器的被执行顺序是比较重要的!这依赖于具体的实现需求。
如果需求有要求:参数为null时直接返回一个null的结果,停止调用过程,那么我们可以把上面的方法改成这样:
public
Result intercept(Action action){ Paramemter param
=
action.getParam();
if
(param
==
null
){
return
null
; }
//
继续调用过程
return
action.invoke(); }
所以,在所有的拦截器的实现中,action.invoke()这一行代码的位置或者有无非常重要,通过控制它我们就能在调用的前后进行拦截,甚至不调用它!
public
interface
MoneyAware{
public
void
setMoney(
int
money); }
//
依赖注入拦截器
public
DependencyInjector
implements
Interceptor{
public
Result intercept(Action action){
//
如果它实现了MoneyAware接口,那么我们就给它注入5毛钱
if
(action
instanceof
MoneyAware){ action.setMoney(
5
); }
//
继续调用过程
return
action.invoke(); } }
从这个拦截器可以看出,我们能修改被拦截对象的内部状态。
//
结果格式化拦截器
public
ResultFormater
implements
Interceptor{
public
Result intercept(Action action){
//
先调用要拦截的方法
result
=
action.invoke();
//
将结果格式化
formatResult(result);
//
返回结果
return
result; } }
这个拦截器就是方法调用后的拦截,所以这种拦截器被执行的时候被放在调用堆栈的最下面,当其他拦截器执行完后,它才被执行!
特别说明:本人转载文章纯为技术学习,总结经验,并无其他目的,若有他人继续转载,请链接原作者的地址,而不是本文的地址,以示对作者的尊重。最后对原作者的辛勤劳动表示感谢!