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

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 启动慢的原因之一),执行速度较快。可以通过缓存加速编译~


                
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值