长梦留痕小说结局:java代理(Proxy)模式浅析
来源:百度文库 编辑:九乡新闻网 时间:2024/04/28 23:16:41
Java代码
/*
* 实现一个简单的代理类,代码来自《java与模式》该例子
* 的任务是为一个Vector对象提供一个代理对象,当Vector
* 的任何方法被调用之前和调用之后,分别打印出两条信息,
* 这表明这个代理对象有能力截获和控制这个Vector对象。
*/
public class VectorProxy implements InvocationHandler{
//包含被代理的对象,这里是一个Vector
private Object targetObj;
//为被代理对象设置一个get方法,这里只是我用来测试所用
public Object getTargetObj() {
return targetObj;
}
//构造方法,并接受被代理对象作为参数
public VectorProxy(Object targetObj) {
this.targetObj = targetObj;
}
//一个静态工厂方法,用来获得代理对象,传递被代理对象作为参数
public static Object factory(Object obj) {
Class clazz = obj.getClass();
//调用newProxyInstance方法得到一个代理对象,这个方法下面会详述
Object proxy = Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new VectorProxy(obj));
return proxy;
}
//实现InvocationHandler接口的invoke方法,该方法会被自动调用
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before invoke:" + method.getName()); //调用被代理对象某方法之前执行一句打印
if(args != null) {
for(Object o:args)
System.out.println(o);
}
//通过代理对象获得被代理对象,首先调用Proxy的静态方法getInvocationHandler,并传递代理对象获得代理类中
//关联的InvaocationHandler的实现类对象,再接着调用我们上面定义的获取被代理对象的get方法
Object tarObj = ((VectorProxy)(Proxy.getInvocationHandler(proxy))).getTargetObj();
System.out.println(tarObj == targetObj); //测试通过上面方法获得的被代理对象是否就是当前VectorProxy实例中的对象
Object resultObj = method.invoke(tarObj, args); //这里直接传递targetObj即可,对被代理对象调用某方法,并传递参数
System.out.println("after invoke:" + method.getName()); //调用被代理对象某方法之后执行一句打印
return resultObj;
}
public static void main(String[] args) {
List v = null;
//new Vector(10)是被代理对象,它被传入InvocationHandler中,作为成员变量,InvocationHandler的实现类也会作为Proxy的成员变量
v = (List) factory(new Vector(10));
//对代理对象调用被代理对象所拥有的方法,此时会自动调用Proxy中关联的VectorProxy实例的invoke方法
v.add("NEW");
System.out.println(v.get(0));
}
}
上面的代码中我们创建类VectorProxy并实现InvocationHandler接口,当然它需要实现InvocationHandler接口中的invoke方法了。
我们首先需要创建一个代理对象,并在代理对象中指定被代理对象,以及指定被代理对象的所有实现接口:
Class clazz = obj.getClass(); //obj为被代理对象
Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new VectorProxy(obj)); //传递三个参数:被代理对象的类加载器,被代理对象所实现的接口数组以及一个InvocationHandler实现类对象,注意这个实现类对象中包含了被代理对象。
现在我们就用生成的代理对象来代替被代理对象,直接对代理对象进行操作。
当Client需要调用被代理对象中的方法时,这些方法是它所实现接口中的方法( getInterfaces() ),此时我们是对代理对象调用这些方法,代理对象便会自动调用代理对象中相关联的InvocationHandler实现类的invoke方法,即我们实现的
public Object invoke(Object proxy, Method method, Object[] args)
我们可以在invoke方法中实现我们需要的逻辑,包括调用被代理对象对应的方法:
method.invoke(targetObject,args) //targetObject为被代理对象,被代理对象是作为InvocationHandler实现类的成员变量,args为传递给方法的参数,
还可以在调用被代理对象相关方法之前和之后执行某些操作。
当我们对代理对象执行某些操作,这些操作和对被代理对象执行的操作一样,其实我们的本意也是对被代理对象进行某些操作,在本例中,即在vector中添加,删除,获取对象等。此时会自动调用代理对象中相关联的InvocationHandler接口的实现类的invoke方法,同时将代理对象,被调用的方法以及方法的参数作为参数传递给invoke,因此我们便可以在invoke中实现我们需要的操作。
JDK 中具体的动态代理类是怎么产生的呢?
1.产生代理类$Proxy0 类
执行了 Proxy. newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)将产生$Proxy0 类,它继承Proxy 对象,并根据第二个参数,实现了被代理类的所有接口,自然就可以生成接口要实现的所有方法了(这时候会重写hashcode ,toString 和equals 三个方法),但是还没有具体的实现体;2.将代理类$Proxy0 类加载到JVM 中
这时候是根据 Proxy. newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 它的第一个参数---- 就是被代理类的类加载器,把当前的代理类加载到JVM 中
3.创建代理类$Proxy0 类的对象
调用的$Proxy0 类的$Proxy0 (InvocationHandler )构造函数,生成$Proxy0 类的对象
参数就是 Proxy. newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 它的第三个参数
这个参数就是我们自己实现的InvocationHandler 对象,我们知道InvocationHandler 对象中组合加入了代理类代理的接口类的实现类;所以,$Proxy0 对象调用所有要实现的接口的方法,都会调用InvocationHandler 对象的invoke ()方法实现;
4.生成代理类的class byte
动态代理生成的都是二进制class 字节码