您的位置:首页 > 编程语言 > Java开发

【JAVA笔记——道】java动态代理源码深入

2015-01-04 20:25 337 查看
JAVA动态代理是JAVA7的重要特性,其主要功能是通过proxy对象实现动态接口实现。

public class PracticeInvocationHandler implements InvocationHandler{
private Object receiverObject;

public PracticeinvocationHandler(Object object) {
this.receiverObject = object;
}

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("调用方法" + method.getName());
System.out.println("参数列表" + Arrays.deepToString(args));
return method.invoke(receiverObject, args);
}

}


新建PracticeObject与PracticeObjectImpl,此处只是举例Impl没有具体实现

public interface PracticeObject extends Comparable{
}

public class PracticeObjectImpl implements PracticeObject {

public int compareTo(Object o) {

return 0;
}

}


具体实现方式上
public class PracticeProxy {

public static void main(String[] args) {
String str = "Hello World";
PracticeInvocationHandler handler = new PracticeInvocationHandler(str);
ClassLoader loader = PracticeObject.class.getClassLoader();
PracticeObject obj = (PracticeObject) Proxy.newProxyInstance(loader, new Class[]{PracticeObject.class}, handler);
obj.compareTo("Good");
}
}

接下来我们使用Debug进行源码深入剖析,Into Proxy.newProxyInstance之后抛开错误检验相关进入第一个重要的方法
/*
* Look up or generate the designated proxy class.
*/
Class cl = getProxyClass(loader, interfaces);
<span style="font-family: Arial, Helvetica, sans-serif; white-space: normal; background-color: rgb(255, 255, 255); ">
</span>
<span style="font-family: Arial, Helvetica, sans-serif; white-space: normal; background-color: rgb(255, 255, 255); ">深入此方法,一个for循环中进行错误率的检测之后,我们可以看到</span>
<span style="font-family: Arial, Helvetica, sans-serif; white-space: normal; background-color: rgb(255, 255, 255); ">/*
<span style="white-space:pre">	</span> * Using string representations of the proxy interfaces as
<span style="white-space:pre">	</span> * keys in the proxy class cache (instead of their Class
<span style="white-space:pre">	</span> * objects) is sufficient because we require the proxy
<span style="white-space:pre">	</span> * interfaces to be resolvable by name through the supplied
<span style="white-space:pre">	</span> * class loader, and it has the advantage that using a string
<span style="white-space:pre">	</span> * representation of a class makes for an implicit weak
<span style="white-space:pre">	</span> * reference to the class.
 */
</span>
<span style="font-family:Arial, Helvetica, sans-serif;"><span style="white-space: normal; "><span style="color:#cc6600;font-weight: bold; ">用字符串表示代理接口  作为 代理缓存的 标识(而不是类的对象) 就已经足够,因为我们仅仅需要代理接口可以被类加载器识别。这种方式有一个有点,这只是一个弱引用</span></span></span><pre name="code" class="java">/*
* Find or create the proxy class cache for the class loader.
*/
Map cache;
synchronized (loaderToCache) {
cache = (Map) loaderToCache.get(loader);
if (cache == null) {
cache = new HashMap();
loaderToCache.put(loader, cache);
}
/*
* This mapping will remain valid for the duration of this
* method, without further synchronization, because the mapping
* will only be removed if the class loader becomes unreachable.
*/
}

此处的loaderToCache是一个WeakHashMap(线程安全),在这将类装载器装入并对应生成一个空HashMap

Spring通过CgLib实现 动态代理(另外一种实现动态代理方式)

CgLib是一个开源动态代理框架,基于ASM实现动态代理。相较JDK Proxy技术,编译速度相对慢(Spring 启动慢的原因之一),执行速度较快。可以通过缓存加速编译~


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: