拦截器是调用方法的改进.当称某个实例是拦截器是,这是就其行为上而言的;
从代码的角度来看,拦截器就是一个类,这个类也包含方法,只是这个方法是个特殊方法,它会在目标方法调用之前“自动”执行。
//拦截器方法大都是通过代理的方式来调用的
//jdk动态代理只能对实现了接口的实例来生成代理,因此必须提供一个接口:
public interface Dog {
public void info();
public void run();
}
//它的实现:
public class DogImpl implements Dog {
public void info() {
System.out.println("我是一直猎狗!;);
}
public void run() {
System.out.println("我奔跑迅速!;);
}
}
//拦截dog实例的拦截器类:
public class DogIntercepter {
public void method1(){
System.out.println("111111111模拟通用方法一!;);
}
public void method2(){
System.out.println("222222222模拟通用方法二!;);
}
}
称其为拦截器,只是就它的行为而言,并不是它在代码实现上与普通java类有什么特别之处
关键是下面的ProxyHandler类,该类实现InvocationHandler接口,该接口可以动态调用目标对象的方法
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyHandler implements InvocationHandler {
private Object target;
DogIntercepter di = new DogIntercepter();
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
Object result = null;
if(method.getName().equals("info")){
di.method1();
result = method.invoke(target, args);
di.method2();
}else{
result = method.invoke(target, args);
}
return result;
}
public void setTarget(Object o){
this.target = o;
}
}
其与上面的两个地方耦合:
2.与被拦截的方法耦合:上面类制定拦截器名为info的方法
这两个耦合也需要解决,通常的解决方案是将拦截器类放在配置文件中指定,将需要被拦截的目标方法也放在配置文件中指定。
系统还需要一个代理工厂,代理工厂的主要作用是更具目标对象生成一个代理对象。
public class MyProxyFactory {
public static Object getProxy(Object object){
ProxyHandler handler = new ProxyHandler();
handler.setTarget(object);
//第一个参数是用来创建动态代理的ClassLoader对象,只要该对象能访问Dog接口即可
//第二个参数是接口数组,正是代理该接口的数组
//第三个参数是代理包含的处理实例
return Proxy.newProxyInstance(DogImpl.class.getClassLoader(),
object.getClass().getInterfaces(), handler);
}
}
主程序:
public class TestDog {
public static void main(String[] args) {
Dog targetObject = new DogImpl();
Dog dog = null;
Object proxy = MyProxyFactory.getProxy(targetObject);
if(proxy instanceof Dog){
dog = (Dog)proxy;
}
dog.info();
dog.run();
}
}