黑马程序员技术交流社区
标题:
动态代理的疑惑?求大神们解答
[打印本页]
作者:
谢洋
时间:
2013-3-3 09:24
标题:
动态代理的疑惑?求大神们解答
1、我发现代理类只实现了目标类的接口上的基本功能,而没包括目标类的所有功能?是实现不了?还是有别的原因?想不通啊
2、如果我要让代理类具有目标类所有的功能,应该怎么办?
作者:
唐长智
时间:
2013-3-3 10:34
本帖最后由 唐长智 于 2013-3-3 10:51 编辑
楼主的这个问题也困扰我很久了,于是早上我就找源代码开读。在Proxy的源代码里关于newProxyInstance是这么写的
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
if (h == null) {
throw new NullPointerException();
}
Class cl = getProxyClass(loader, interfaces);
//通过getProxyClass方法得到Class对象
try {
Constructor cons = cl.getConstructor(constructorParams);
//用Class对象的构造方法来创建实例对象,也就是代理实例
return (Object) cons.newInstance(new Object[] { h });
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
} catch (IllegalAccessException e) {
throw new InternalError(e.toString());
} catch (InstantiationException e) {
throw new InternalError(e.toString());
} catch (InvocationTargetException e) {
throw new InternalError(e.toString());
}
}
复制代码
关键就在getProxyClass这个方法上,看他是怎么得到Class对象的。这个方法的源码实在太长,太复杂我不能完全看懂,就只能把关于ProxyClass相关的源码粘过来
byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces);
//是根据接口的Class对象来生成的
try {
// 动态地定义新生成的代理类
proxyClass = defineClass0(loader, proxyName, proxyClassFile, 0,
proxyClassFile.length);
} catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
复制代码
通过这两段源码你就能看出来在newProxyInstance()方法的设计中,就是用传入的接口的Class对象得到构造函数来生成代理实例的,所以也就只能具备接口的功能。
作者:
谢洋
时间:
2013-3-3 11:56
谢谢楼上哥们
1、从
Class cl = getProxyClass(loader, interfaces);
Constructor cons = cl.getConstructor(constructorParams);
//用Class对象的构造方法来创建实例对象,也就是代理实例
return (Object) cons.newInstance(new Object[] { h });
可以看出你说的:就是用传入的接口的Class对象得到构造函数来生成代理实例的,所以也就只能具备接口的功能,有根有据;
2、但是我还有一点不明白:因为接口没有方法体,表明代理的方法体是从目标类身上获取的,也就说明loader可以搞到目标类的字节码;
a、从这一点来看,即然可以拿到目标类的字节码,让代理类去拥有目标类的所有方法是可以行得通的,那么为什么代理类不去实现
目标类的所有功能,再添加一些自已的功能?
b、还是因为构造函数是接口的,就只能实现接口的中的方法?个人解理:因为对象的由构造函数构造出来,
而构造函数里面的信息(
记录着产生一个具有什么样功的的对象的信息)
是固定的,所以说有什么样的构造函数,就有什么样的对象?
这样理解合理不?
c、还有,如果上面解释得通,那么只要搞到目标类的所有构造函数,那不就可以构造出拥有目标类所有功能的代理类了吗?
另外问一个简单的问题,我不知怎么找源码来看,谢谢!
作者:
唐长智
时间:
2013-3-3 14:04
本帖最后由 唐长智 于 2013-3-3 14:36 编辑
好吧,先从简单的说起。
1.源码就在你的JDK里,是一个压缩文件。比如我的源码路径就是jdk1.6.0_35\src.rar
你双击进去就能看到像API里面一样的文件夹分布,直接打开看就行了。
2.在源码中
import sun.misc.ProxyGenerator;
byte[] proxyClassFile =
ProxyGe
nerator.generateProxyClass( proxyName, interfaces)
因为这是sun公司的包,这个方法到底干了什么没办法知道。也就没办法知道字节码到底是怎么生成的。
3.为什么代理类只能实现接口的方法呢?
那是因为java本身就不支持多继承啊。
Objcet dynamicproxy = Proxy.newProxyInstance()
dynamicproxy 是Proxy的实例对象,继承了Objcet。你不能再让它去继承ArrayList或者HashSet等等的类了。
这是我在网上找的IBM的帖子,关于动态代理讲的很详细
http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/index.html
作者:
谢洋
时间:
2013-3-3 14:22
非常谢谢
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2