拦截器主要用于拦截用户请求并作相应的处理.
例如, Spring MVC通过拦截器可以进行权限验证、记录日志等; Mybatis通过插件实现分页功能, 而这个插件就是拦截器.
架构图如下:
拦截器一般都是使用代理模式+责任链一起实现的, 下面一起看下这两种设计模式.
一. 代理模式
代理模式给某一个对象提供一个代理对象, 并由代理对象控制对原对象的引用.
代理模式是非常常见一个设计模式, 一般分为动态代理和静态代理, 我们以动态代理为例看下, 如何实现一套代理模式.
代理模式主要分为三部分: 接口, 实现类, 代理类.
接口:
public interface UserService {
void addUser();
}
实现类:
public class UserServiceImpl implements UserService {
public UserServiceImpl() {
}
public void addUser() {
System.out.println("this is addUser() method!");
}
}
代理类:
public class UserServiceInvocationHandler implements InvocationHandler {
private Object targetObject;
public UserServiceInvocationHandler(Object targetObject) {
this.targetObject = targetObject;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("do something");
Object result = method.invoke(targetObject, args);
return result;
}
}
测试类:
private static void test1() {
UserService targetObject = new UserServiceImpl();
UserServiceInvocationHandler proxy = new UserServiceInvocationHandler(targetObject);
UserService object = (UserService) Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), proxy);
object.addUser();
}
二. 责任链模式
为方便多个代理的扩展, 还需要引入过责任链模式. 责任链模式是一种对象的行为模式. 在责任链模式里, 很多对象由包含下一个对象引用的对象而连接起来形成一条链. 请求在这个链上传递, 直到链上的某一个对象决定处理此请求. 责任链设计模式能够根据配置, 自由组合, 动态调用.
责任链模式实现代码主要分为三部分: 责任链, 链节点, 处理实体.
结合上面的代理模式, 实现代码如下:
责任链:
public class InterceptorChain {
private final List<Interceptor> interceptors = new ArrayList<Interceptor>();
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
public void addInterceptor(Interceptor interceptor) {
interceptors.add(interceptor);
}
public List<Interceptor> getInterceptors() {
return Collections.unmodifiableList(interceptors);
}
}
链节点:
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
}
public class LogInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println(Thread.currentThread().getName()+ "\tlog intercept..."+ invocation.toString());
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
}
处理实体:
public interface UserService {
void addUser();
}
public class UserServiceImpl implements UserService {
public UserServiceImpl() {}
public void addUser() {
System.out.println("this is addUser() method!");
}
}
测试类
private static void test2() {
InterceptorChain chain = new InterceptorChain();
chain.addInterceptor(new LogInterceptor());
UserService service = new UserServiceImpl();
UserService object = (UserService) chain.pluginAll(service);
object.addUser();
}
为适应更多应用场景, 可以在invoke()方法前后分别抽象出perHandler()和postHandler()方法, 进行更多扩展.
注: 这里的类设计来源于mybatis的plugin模块.
总结
万物之始, 大道至简, 衍化至繁.
通过代理和责任链两个非常简单的模式, 就可以设计出高扩展性, 低耦合的架构.