參考鏈接:http://www.reibang.com/p/3ad3fb560ca1
首先看調(diào)用方式:
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)临谱;
函數(shù)中調(diào)用getProxyClass函數(shù),動態(tài)生成一個RealSubject類相關(guān)的.Class類猫牡,newProxyInstance函數(shù)中將handler作為回調(diào)傳遞進(jìn)去卷胯,里面調(diào)用Proxy類中的static的invoke回調(diào)出來也就是到RealSubject的invoke方法中,做一些額外的事情辜贵。
// 代理對象是可以序列化
public class Proxy implements Serializable {
一悯蝉、定義的變量:
1、private static final long serialVersionUID = -2222568056686623797L;
serialVersionUID的作用:
通過判斷實體類的serialVersionUID來驗證版本一致性的托慨。在進(jìn)行反序列化時鼻由,JVM會把傳來的字節(jié)流中的serialVersionUID與本地相應(yīng)實體類的serialVersionUID進(jìn)行比較,如果相同就認(rèn)為是一致的厚棵,可以進(jìn)行反序列化蕉世,否則就會出現(xiàn)序列化版本不一致的異常。
生成實體類的serialVersionUID方法:1婆硬、寫上默認(rèn)的1L讨彼,比如:private static final long serialVersionUID = 1L; 2、用idea自動生成柿祈。
// maps class loaders to created classes by interface names
/** 將代理類 加載器放在Proxy的maps結(jié)構(gòu)中緩存起來 */
2哈误、private static final Map<ClassLoader, Map<String, WeakReference<Class<?>>>> loaderCache = new WeakHashMap<ClassLoader, Map<String, WeakReference<Class<?>>>>();
/** 所有代理類的集合哩至,用于isProxyClass方法的實現(xiàn) */
3、private static final Map<Class<?>, String> proxyCache = new WeakHashMap<Class<?>, String>();
4蜜自、private static int NextClassNameIndex = 0;///** 下一個用于生成唯一代理類名字的數(shù)字 */
/**
* The invocation handler on which the method calls are dispatched.
* 代理實例的invocationHandler對象
*/
5菩貌、protected InvocationHandler h;
二:定義的方法:
作用類實現(xiàn)了InvocationHandler接口的代理類,其中主要方法有:
private Proxy() {} ("unused") //禁止實例化
protected Proxy(InvocationHandler h):構(gòu)造方法重荠,用于給內(nèi)部的h賦值箭阶。
static Class getProxyClass(ClassLoader loader, Class[] interfaces):獲得一個動態(tài)代理類的Class對象。戈鲁,其中l(wèi)oader是類裝載器仇参,interfaces是真實類所擁有的全部接口的數(shù)組。 從緩存中取婆殿,如果沒有诈乒,則調(diào)用本地方法generateProxy(name, interfaces, loader, methodsArray, exceptionsArray);注意其中的幾個參數(shù)。
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理類的一個實例婆芦,返回后的代理類可以當(dāng)作被代理類使用怕磨。
InvocationHandler.invoke的第一個參數(shù)proxy值,是newProxyInstance返回的動態(tài)代理類的實例消约,不是被代理的實例(下方的demo輸出的className證明了這一點)肠鲫。
動態(tài)代理類Proxy是結(jié)合java底層實現(xiàn)的,通過純粹的java代碼實現(xiàn)比較困難或粮。
需要java動態(tài)生成類的支持导饲。
根據(jù)class在Map 中查找是否是代理類
public static boolean isProxyClass(Class<?> cl) {}
返回指定代理實例的調(diào)用處理程序。
public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException {
兩個 native方法
native private static Class generateProxy(String name, Class[] interfaces,ClassLoader loader);
在生成代理類時氯材,VM克隆該方法的描述符渣锦。沒有實現(xiàn)。
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