回顧:
????上一篇代理之JDK動(dòng)態(tài)代理我們了解來JDK動(dòng)態(tài)代理的使用。同樣也遺留了兩個(gè)問題:1备埃、代理對(duì)象是怎么生成的闺魏?2、InvocationHandler的invoke方法是由誰來調(diào)用的晶框?
jdk動(dòng)態(tài)代理源碼:
????首先來看一下JDK是怎樣生成代理對(duì)象的。既然生成代理對(duì)象是用的Proxy類的靜態(tài)方newProxyInstance叁扫,那么我們就去它的源碼里看一下它到底都做了些什么三妈?
Java1.8 源碼(以下代碼代碼不全,只截取關(guān)鍵性代碼):
/**??
*?loader:類加載器??
*?interfaces:目標(biāo)對(duì)象實(shí)現(xiàn)的接口??
*?h:InvocationHandler的實(shí)現(xiàn)類??
*/??
public static Object newProxyInstance(ClassLoader loader,Class[] interfaces, ? ? ? ? ? ? ? ? ?
????????????????????????????????????InvocationHandler h)throws IllegalArgumentException{
? ? //判斷h不能為null莫绣。為null 拋出:NullPointerException
? ? ?Objects.requireNonNull(h);
? ? final Class[] intfs = interfaces.clone();
????????//查找或生成指定的代理類
? ? ? ?Class cl =getProxyClass0(loader, intfs);
? ? ? try {
????????//獲取構(gòu)造方法
????????final Constructor cons = cl.getConstructor();
? ? ? ? final InvocationHandler ih = h;
? ??????//如果構(gòu)造方法不是public 設(shè)置構(gòu)造方法為可訪問
? ? ? ? if (!Modifier.isPublic(cl.getModifiers())) {
????????????AccessController.doPrivileged(new PrivilegedAction() {
????????????????public Void run() {
????????????????????cons.setAccessible(true);
????????????????????return null;
? ? ? ? ? ? ? ? }
????????});????
? ? ? ? }
? ? ????/ /放射創(chuàng)建對(duì)象
????????return cons.newInstance(new Object[]{h});
? ? }catch (Exception e) {
????????????throw new InternalError(e.toString(), e);
? ? }
}
以上代碼可以看出:通過newProxyInstance方法是getProxyClass0獲取Class對(duì)象畴蒲,后通過反射創(chuàng)建對(duì)象。那getProxyClass0就看看getProxyClass0是什么獲取Class對(duì)象的:
private static ClassgetProxyClass0(ClassLoader loader, Class... interfaces) {
????//這里限制了目標(biāo)對(duì)象實(shí)現(xiàn)的接口的個(gè)數(shù)
?????if (interfaces.length >65535) {
????????????throw new IllegalArgumentException("interface limit exceeded");
? ? }
? ?return proxyClassCache.get(loader, interfaces);
}
/*
*如果緩存中有对室,就直接返回模燥,否則會(huì)生成
*key:類加載器咖祭;parameter:接口數(shù)組
*/
public V get(K key, P parameter) {
? ? //省略部分緩存機(jī)制代碼
? ? ...
? ? Factory factory =null;
? ??//下面用到了 CAS+重試 實(shí)現(xiàn)的多線程安全的 非阻塞算法
? ? while (true) {
? ? ? ? //最終執(zhí)行的代碼 從supplier.get()中獲取返回值
????????if (supplier !=null) {
? ? ? ? ? ? V value = supplier.get();
? ? ? ? ? ? if (value !=null) {
????????????????return value;
? ? ? ? ? ? }
????????}
? ? ? ? if (factory ==null) {
????????????factory =new Factory(key, parameter, subKey, valuesMap);
? ? ? ? }
????????if (supplier ==null) {
????????????supplier = valuesMap.putIfAbsent(subKey, factory);
? ? ? ? ? ? if (supplier ==null) {
? ? ? ? ? ? ? ? supplier = factory;
? ? ? ? ? ? }
? ? ? ? }else {
????????????if (valuesMap.replace(subKey, supplier, factory)) {
? ? ? ? ? ? ? ? supplier = factory;
? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? supplier = valuesMap.get(subKey);
? ? ? ? ? ? }
????????}
????}
}
以上代碼重點(diǎn)是:?V value = supplier.get() 獲取最終的返回的class對(duì)象
public synchronized V get() {
? ? ? ? Supplier supplier =valuesMap.get(subKey);
? ? ? ? if (supplier !=this) {
? ? ? ? ? ? return null;
? ? ? ? }
? ? ? ? V value =null;
? ? ? ? try {
? ? ? ? ? ? //這里是創(chuàng)建返回Class對(duì)象(valueFactory.apply(key, parameter))
????????????value = Objects.requireNonNull(valueFactory.apply(key, parameter));
? ? ? ? }finally {
????????if (value ==null) {
? ? ? ? ? ? ? ? valuesMap.remove(subKey, this);
? ? ? ? ? ? }
}
? ? ? ? assert value !=null;
? ? ? ? CacheValue cacheValue =new CacheValue<>(value);
? ? ? ? reverseMap.put(cacheValue, Boolean.TRUE);
? ? ? ? if (!valuesMap.replace(subKey, this, cacheValue)) {
????????????throw new AssertionError("Should not reach here");
? ? ? ? }
?? ? ? ?return value;
? ? }
}
我們繼續(xù)關(guān)注:valueFactory.apply方法看看是什么創(chuàng)建Class對(duì)象的:
? ? public Classapply(ClassLoader loader, Class[] interfaces) {
????????Map, Boolean> interfaceSet =new IdentityHashMap<>(interfaces.length);
? ? ? ? for (Class intf : interfaces) {
? ? ? ? ? ? Class interfaceClass =null;
? ? ? ? ? ? try {
????????????????//?加載目標(biāo)類實(shí)現(xiàn)的接口到內(nèi)存中?
????????????????interfaceClass = Class.forName(intf.getName(), false, ????);
? ? ? ? ? ? }catch (ClassNotFoundException e) {
????????????}
????????????if (interfaceClass != intf) {
????????????????throw new IllegalArgumentException(intf +" is not visible from class loader");
? ? ? ? ? ? }
? ? ? ? ? ? //如果不是接口 就拋IllegalArgumentException
? ? ? ? ? ? if (!interfaceClass.isInterface()) {
????????????????throw new IllegalArgumentException(
????????????????????interfaceClass.getName() +" is not an interface");
? ? ? ? ? ? }
? ? ? ? ? ? if (interfaceSet.put(interfaceClass, Boolean.TRUE) !=null) {
????????????????throw new IllegalArgumentException(
????????????????????"repeated interface: " + interfaceClass.getName());
? ? ? ? ? ? }
}
????????String proxyPkg =null; ??
? ? ? ? int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
? ? ? ?// 驗(yàn)證所有非公共代理接口都在同一個(gè)包中。如果不是者拋異常
? ? ? ? for (Class intf : interfaces) {
????????????int flags = intf.getModifiers();
? ? ? ? ? ? if (!Modifier.isPublic(flags)) {
????????????accessFlags = Modifier.FINAL;
? ? ? ? ? ? ? ? String name = intf.getName();
? ? ? ? ? ? ? ? int n = name.lastIndexOf('.');
? ? ? ? ? ? ? ? String pkg = ((n == -1) ?"" : name.substring(0, n +1));
? ? ? ? ? ? ? ? if (proxyPkg ==null) {
????????????????????proxyPkg = pkg;
? ? ? ? ? ? ? ? }else if (!pkg.equals(proxyPkg)) {
????????????????????throw new IllegalArgumentException(
????????????????????????"non-public interfaces from different packages");
? ? ? ? ? ? ? ? }
????????????}
????????}
????????if (proxyPkg ==null) {
? ? ? ? ? ? proxyPkg = ReflectUtil.PROXY_PACKAGE +".";
? ? ? ? }
? ? ? ? long num =nextUniqueNumber.getAndIncrement();
? ? ? ? String proxyName = proxyPkg +proxyClassNamePrefix + num;
? ? ? ? //這個(gè)是重點(diǎn):生成類字節(jié)碼的方法
? ? ? ? byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
????????????????proxyName, interfaces, accessFlags);
? ? ? ? try {
? ??????????//?根據(jù)代理類的字節(jié)碼生成代理類的實(shí)例??
????????????return defineClass0(loader, proxyName, proxyClassFile, 0, ? ?
????????????????????????????????????????????????proxyClassFile.length);
? ? ? ? }catch (ClassFormatError e) {
? ? ? ? ? ? throw new IllegalArgumentException(e.toString());
? ? ? ? }
}
}
我們繼續(xù)跟蹤ProxyGenerator.generateProxyClass方法:????
public static byte[] generateProxyClass(final String var0, Class[] var1, int var2) {
????ProxyGenerator var3 =new ProxyGenerator(var0, var1, var2);
? ? //真正生成字節(jié)碼的方法
? ? final byte[] var4 = var3.generateClassFile();
//如果saveGeneratedFiles為true 則生成字節(jié)碼文件蔫骂,所以在開始我們要設(shè)置這個(gè)參數(shù)
? ? if (saveGeneratedFiles) {
????????????AccessController.doPrivileged(new PrivilegedAction() {
????????????????public Void run() {
????????????????try {
????????????????????int var1 = var0.lastIndexOf(46);
? ? ? ? ? ? ? ? ? ? Path var2;
? ? ? ? ? ? ? ? ? ? if (var1 >0) {
????????????Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
? ? ? ? ? ? ? ? ? ? ? ? Files.createDirectories(var3);
? ? ? ? ? ? ? ? ? ? ? ? var2 = var3.resolve(var0.substring(var1 +1, var0.length()) +".class");
? ? ? ? ? ? ? ? ? ? }else {
????????????????????????var2 = Paths.get(var0 +".class");
? ? ? ? ? ? ? ? ? ? }
????????????????Files.write(var2, var4, new OpenOption[0]);
????????????????return null;
? ? ? ? ? ? ? ? }catch (IOException var4x) {
? ? ? ? ? ? ? ? ? ? ? ?throw new InternalError("I/O exception saving generated file: " + var4x);
? ? ? ? ? ? ? ? }
????????}
????????????});
? ? }
????????return var4;
}
var3.generateClassFile為正真創(chuàng)建字節(jié)碼的方法么翰,涉及字節(jié)碼文件的語法,在此我們就不在深入的探究辽旋。
總結(jié):代理對(duì)象是的創(chuàng)建過程一共分三個(gè)步驟:
? ??1浩嫌、ProxyGenerator.generateProxyClass方法負(fù)責(zé)生成代理類的字節(jié)碼,生成邏輯比較復(fù) ? ? ? ? ? ? ? ? ? ?雜补胚,了解原理繼續(xù)分析源碼?sun.misc.ProxyGenerator码耐;
????2、native方法Proxy.defineClass0負(fù)責(zé)字節(jié)碼加載的實(shí)現(xiàn)溶其,并返回對(duì)應(yīng)的Class對(duì)象骚腥。
? ??3、利用clazz.newInstance反射機(jī)制生成代理類的對(duì)象瓶逃;
至此我們明白了代理對(duì)象是怎么生成的束铭,那么InvocationHandler的invoke方法是由誰來調(diào)用的?厢绝?契沫?
“知其然,知其所以然”