zoukankan      html  css  js  c++  java
  • 【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 启动慢的原因之一),执行速度较快。可以通过缓存加速编译~

    
                
    
  • 相关阅读:
    python hashlib模块
    OS模块-提供对操作系统进行调用的接口
    For循环
    python --time()函数
    使用docker部署prometheus和grafana 并监控mysql 配置告警
    记换换回收一个js逆向分析
    mitmproxy 在windows上的使用
    elasticsearch_dsl 的nested
    利用谷歌插件破解今日头条的新闻ajax参数加密,新手都能懂
    aiohttp爬虫的模板,类的形式
  • 原文地址:https://www.cnblogs.com/cunchen/p/9464238.html
Copyright © 2011-2022 走看看