參考鏈接:http://www.lxweimin.com/p/3ad3fb560ca1
首先看調用方式:
Subject realSubject = new RealSubject();
InvocationHandler handler = new DynamicProxyHandler(realSubject);
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);
通過Proxy的
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h);
函數中調用getProxyClass函數,動態生成一個RealSubject類相關的.Class類,newProxyInstance函數中將handler作為回調傳遞進去,里面調用Proxy類中的static的invoke回調出來也就是到RealSubject的invoke方法中,做一些額外的事情。
// 代理對象是可以序列化
public class Proxy implements Serializable {
一、定義的變量:
1、private static final long serialVersionUID = -2222568056686623797L;
serialVersionUID的作用:
通過判斷實體類的serialVersionUID來驗證版本一致性的。在進行反序列化時,JVM會把傳來的字節流中的serialVersionUID與本地相應實體類的serialVersionUID進行比較,如果相同就認為是一致的,可以進行反序列化,否則就會出現序列化版本不一致的異常。
生成實體類的serialVersionUID方法:1、寫上默認的1L,比如:private static final long serialVersionUID = 1L; 2、用idea自動生成。
// maps class loaders to created classes by interface names
/** 將代理類 加載器放在Proxy的maps結構中緩存起來 */
2、private static final Map<ClassLoader, Map<String, WeakReference<Class<?>>>> loaderCache = new WeakHashMap<ClassLoader, Map<String, WeakReference<Class<?>>>>();
/** 所有代理類的集合,用于isProxyClass方法的實現 */
3、private static final Map<Class<?>, String> proxyCache = new WeakHashMap<Class<?>, String>();
4、private static int NextClassNameIndex = 0;///** 下一個用于生成唯一代理類名字的數字 */
/**
* The invocation handler on which the method calls are dispatched.
* 代理實例的invocationHandler對象
*/
5、protected InvocationHandler h;
二:定義的方法:
作用類實現了InvocationHandler接口的代理類,其中主要方法有:
private Proxy() {} ("unused") //禁止實例化
protected Proxy(InvocationHandler h):構造方法,用于給內部的h賦值。
static Class getProxyClass(ClassLoader loader, Class[] interfaces):獲得一個動態代理類的Class對象。,其中loader是類裝載器,interfaces是真實類所擁有的全部接口的數組。 從緩存中取,如果沒有,則調用本地方法generateProxy(name, interfaces, loader, methodsArray, exceptionsArray);注意其中的幾個參數。
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理類的一個實例,返回后的代理類可以當作被代理類使用。
InvocationHandler.invoke的第一個參數proxy值,是newProxyInstance返回的動態代理類的實例,不是被代理的實例(下方的demo輸出的className證明了這一點)。
動態代理類Proxy是結合java底層實現的,通過純粹的java代碼實現比較困難。
需要java動態生成類的支持。
根據class在Map 中查找是否是代理類
public static boolean isProxyClass(Class<?> cl) {}
返回指定代理實例的調用處理程序。
public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException {
兩個 native方法
native private static Class generateProxy(String name, Class[] interfaces,ClassLoader loader);
在生成代理類時,VM克隆該方法的描述符。沒有實現。
native private static void constructorPrototype(InvocationHandler h);
public static void main(String[] args) {
Subject realSubject = new RealSubject();
InvocationHandler handler = new DynamicProxyHandler(realSubject);
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);
System.out.println(subject.getClass().getName());
subject.rent();
subject.hello("world");
}
subject.getClass().getName()打印的值是:$Proxy0