在文章:JAVA設計模式-動態代理(Proxy)示例及說明中,爲動態代理設計模式舉了一個小小的例子,那麼這篇文章就來分析一下源碼的實現。html
一,Proxy.newProxyInstance方法java
1 @CallerSensitive 2 public static Object newProxyInstance(ClassLoader loader, 3 Class<?>[] interfaces, 4 InvocationHandler h) 5 throws IllegalArgumentException{ 6 // null檢查,h爲null就拋出NullPointerException 7 Objects.requireNonNull(h); 8 // 將接口類對象數組clone一份。 9 final Class<?>[] intfs = interfaces.clone(); 10 11 //執行權限檢查 12 final SecurityManager sm = System.getSecurityManager(); 13 if (sm != null) { 14 checkProxyAccess(Reflection.getCallerClass(), loader, intfs); 15 } 16 17 /* 18 * Look up or generate the designated proxy class. 19 */ 20 // 查找或者是生成一個特定的代理類對象 21 Class<?> cl = getProxyClass0(loader, intfs); 22 23 /* 24 * Invoke its constructor with the designated invocation handler. 25 */ 26 try { 27 if (sm != null) { 28 checkNewProxyPermission(Reflection.getCallerClass(), cl); 29 } 30 // 是static final 修飾的,源碼: private static final Class<?>[] constructorParams ={ InvocationHandler.class }; 31 // 從代理類對象中查找參數爲InvocationHandler的構造器 32 final Constructor<?> cons = cl.getConstructor(constructorParams); 33 final InvocationHandler ih = h; 34 // 檢測構造器是不是Public修飾,若是不是則強行轉換爲能夠訪問的。 35 if (!Modifier.isPublic(cl.getModifiers())) { 36 AccessController.doPrivileged(new PrivilegedAction<Void>() { 37 public Void run() { 38 cons.setAccessible(true); 39 return null; 40 } 41 }); 42 } 43 // 經過反射,將h做爲參數,實例化代理類,返回代理類實例。 44 return cons.newInstance(new Object[]{h}); 45 } catch (IllegalAccessException|InstantiationException e) { 46 throw new InternalError(e.toString(), e); 47 } catch (InvocationTargetException e) { 48 Throwable t = e.getCause(); 49 if (t instanceof RuntimeException) { 50 throw (RuntimeException) t; 51 } else { 52 throw new InternalError(t.toString(), t); 53 } 54 } catch (NoSuchMethodException e) { 55 throw new InternalError(e.toString(), e); 56 } 57 }
newProxyInstance是Proxy的靜態方法,代碼並不難理解出去權限關的代碼外,就剩下兩步:設計模式
1,獲取代理類對象(21行)數組
2,利用反射技術實例化代理類,並返回實例化對象(44行)緩存
想要詳細的瞭解放射技術,請查閱:Java程序語言的後門-反射機制安全
接下來分析21行中的getProxyClass0方法app
二,Proxy.getProxyClass0方法ide
1 /** 2 * 生成一個代理類對象, 3 * Generate a proxy class. Must call the checkProxyAccess method 4 * to perform permission checks before calling this. 5 */ 6 private static Class<?> getProxyClass0(ClassLoader loader, 7 Class<?>... interfaces) { 8 // 接口類對象數組不能大於65535個,不然拋出異常 9 if (interfaces.length > 65535) { 10 throw new IllegalArgumentException("interface limit exceeded"); 11 } 12 // 從代理類對象緩存中,根據類加載器和接口類對象數組查找代理類對象, 13 // If the proxy class defined by the given loader implementing 14 // the given interfaces exists, this will simply return the cached copy; 15 // otherwise, it will create the proxy class via the ProxyClassFactory 16 return proxyClassCache.get(loader, interfaces); 17 }
在這個方法中,是直接從一個叫proxyClassCache緩存中讀取的,來看一下這個緩存的聲明:oop
//static final private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
這裏涉及到三個類:WeakCache,KeyFactory,ProxyClassFactory,其中後面兩個類都是Proxy類的靜態內部類,從類名能夠大概猜想到,keyFactory是用來生產key的,ProxyClassFactory是用來生產代理類對象的,這個稍後會提到。源碼分析
首先看一下WeakCache類的大概結構:
1 final class WeakCache<K, P, V> { 2 3 private final ReferenceQueue<K> refQueue= new ReferenceQueue<>(); 4 // the key type is Object for supporting null key 5 // key的類型爲Object,支持null key,這裏的null key並非真的能夠使用null最爲key,而是一個new Objdec()對象實例。ConcurrentHashMap,不容許鍵或值null,而HashMap能夠。ConcurrentHashMap是線程安全的,HashMap不是。 6 private final ConcurrentMap<Supplier<V>, Boolean> reverseMap= new ConcurrentHashMap<>(); 7 8 private final BiFunction<K, P, ?> subKeyFactory; 9 private final BiFunction<K, P, V> valueFactory; 10 11 //構造方法 12 public WeakCache(BiFunction<K, P, ?> subKeyFactory, 13 BiFunction<K, P, V> valueFactory) { 14 this.subKeyFactory = Objects.requireNonNull(subKeyFactory); 15 this.valueFactory = Objects.requireNonNull(valueFactory); 16 } 17 18 19 public V get(K key, P parameter) { 20 //下面會詳細介紹這個方法 21 } 22 23 ...... 24 }
上面的源代碼中寫明,代理類對象是從proxyClassCache鎮南關讀取的,接下來就分析WeakCache的get方法
三,WeakCache.get方法
1 // key是類加載器,parameter爲接口類對象數組 2 public V get(K key, P parameter) { 3 // 接口類對象數組null檢查。 4 Objects.requireNonNull(parameter); 5 6 // 刪除過期的條目 7 expungeStaleEntries(); 8 // 生成緩存key對象實例,若是key = null,cacheKey = new Object(); 9 Object cacheKey = CacheKey.valueOf(key, refQueue); 10 11 // lazily install the 2nd level valuesMap for the particular cacheKey 12 // 從緩存map中讀取指定cacheKey的緩存數據valuesMap 13 ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey); 14 15 if (valuesMap == null) { 16 //若是valuesMap爲null,則新增 17 //putIfAbsent方法解釋:若是值存在則返回值,而且不對原來的值作任何更改,若是不存在則新增,並返回null 18 //Absent的意思是缺席,不在 19 ConcurrentMap<Object, Supplier<V>> oldValuesMap= map.putIfAbsent(cacheKey,valuesMap = new ConcurrentHashMap<>()); 20 if (oldValuesMap != null) { 21 valuesMap = oldValuesMap; 22 } 23 } 24 25 // create subKey and retrieve the possible Supplier<V> stored by that 26 // subKey from valuesMap 27 // 獲取subKey,這裏用到了上面提到的Proxy的靜態內部類KeyFactory:subKeyFactory.apply(ket,parameter) 28 Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); 29 // 從valuesMap中獲取supplier 30 Supplier<V> supplier = valuesMap.get(subKey); 31 Factory factory = null; 32 33 while (true) { 34 if (supplier != null) { 35 // supplier might be a Factory or a CacheValue<V> instance 36 // 4,從工廠中獲取代理類對象 37 V value = supplier.get(); 38 if (value != null) { 39 // 5,返回 40 return value; 41 } 42 } 43 // else no supplier in cache 44 // or a supplier that returned null (could be a cleared CacheValue 45 // or a Factory that wasn't successful in installing the CacheValue) 46 47 // lazily construct a Factory 48 if (factory == null) { 49 //1,實例化工廠 50 factory = new Factory(key, parameter, subKey, valuesMap); 51 } 52 53 if (supplier == null) { 54 //2,保存到valuesMap中 55 supplier = valuesMap.putIfAbsent(subKey, factory); 56 if (supplier == null) { 57 // successfully installed Factory 58 // 3,賦值 59 supplier = factory; 60 } 61 // else retry with winning supplier 62 } else { 63 if (valuesMap.replace(subKey, supplier, factory)) { 64 // successfully replaced 65 // cleared CacheEntry / unsuccessful Factory 66 // with our Factory 67 supplier = factory; 68 } else { 69 // retry with current supplier 70 supplier = valuesMap.get(subKey); 71 } 72 } 73 } 74 }
由於程序中Proxy.newProxyInstance是第一次執行,因此while循環開始的時候,supplier,valuesMap都是null。在這個前提下,我爲代碼的執行順序作了一個編號,從1-5執行。
能夠看到第5步,也就是源代碼的第40行將結果返回,那麼,代理類對象就是在第4步,也就是第37行生成的。並且也能夠從第3步,也就是第59行發現supplier就是factory。
那麼接下來,就分析一下Factory.get方法。
四,Factory.get方法
Factory類是WeakCache的內部類。這個類中出去構造方法外,就是get方法了,下面就將這個類的代碼給出:
1 private final class Factory implements Supplier<V> { 2 3 private final K key; 4 private final P parameter; 5 private final Object subKey; 6 private final ConcurrentMap<Object, Supplier<V>> valuesMap; 7 8 Factory(K key, P parameter, Object subKey, 9 ConcurrentMap<Object, Supplier<V>> valuesMap) { 10 this.key = key; 11 this.parameter = parameter; 12 this.subKey = subKey; 13 this.valuesMap = valuesMap; 14 } 15 16 @Override 17 public synchronized V get() { // serialize access 18 // re-check 19 // 檢查 20 Supplier<V> supplier = valuesMap.get(subKey); 21 if (supplier != this) { 22 // something changed while we were waiting: 23 // might be that we were replaced by a CacheValue 24 // or were removed because of failure -> 25 // return null to signal WeakCache.get() to retry 26 // the loop 27 return null; 28 } 29 // else still us (supplier == this) 30 31 // create new value 32 V value = null; 33 try { 34 // valueFactory就是WeakCache的valueFactory屬性,由於Factory是WeakCache的內部類,因此能夠直接訪問WeakCache的valueFactory屬性 35 value = Objects.requireNonNull(valueFactory.apply(key, parameter)); 36 } finally { 37 if (value == null) { // remove us on failure 38 valuesMap.remove(subKey, this); 39 } 40 } 41 // the only path to reach here is with non-null value 42 assert value != null; 43 44 // wrap value with CacheValue (WeakReference) 45 CacheValue<V> cacheValue = new CacheValue<>(value); 46 47 // try replacing us with CacheValue (this should always succeed) 48 if (valuesMap.replace(subKey, this, cacheValue)) { 49 // put also in reverseMap 50 reverseMap.put(cacheValue, Boolean.TRUE); 51 } else { 52 throw new AssertionError("Should not reach here"); 53 } 54 55 // successfully replaced us with new CacheValue -> return the value 56 // wrapped by it 57 return value; 58 } 59 }
關鍵代碼第35行:valueFactory.apply(key, parameter)
這裏的valueFactory就是Proxy的靜態內部類ProxyClassFactory,上面也提到過,那麼就接着分析ProxyClassFactory的apply方法吧。
五,ProxyClassFactory.apply方法
1 /** 2 * 一個利用給定的類加載器和接口類數組生成,定義並返回代理類對象的工廠方法 3 * A factory function that generates, defines and returns the proxy class given 4 * the ClassLoader and array of interfaces. 5 */ 6 private static final class ProxyClassFactory 7 implements BiFunction<ClassLoader, Class<?>[], Class<?>> 8 { 9 // prefix for all proxy class names 10 // 全部代理類對象的前綴 11 private static final String proxyClassNamePrefix = "$Proxy"; 12 13 // next number to use for generation of unique proxy class names 14 // 用於生成惟一代理類名稱的下一個數字 15 private static final AtomicLong nextUniqueNumber = new AtomicLong(); 16 17 @Override 18 public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { 19 20 Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); 21 // 22 for (Class<?> intf : interfaces) { 23 /* 24 * Verify that the class loader resolves the name of this 25 * interface to the same Class object. 26 */ 27 Class<?> interfaceClass = null; 28 try { 29 // 加載接口類,得到接口類的類對象,第二個參數爲false表示不進行實例化 30 interfaceClass = Class.forName(intf.getName(), false, loader); 31 } catch (ClassNotFoundException e) { 32 } 33 if (interfaceClass != intf) { 34 throw new IllegalArgumentException( 35 intf + " is not visible from class loader"); 36 } 37 /* 38 * Verify that the Class object actually represents an 39 * interface. 40 */ 41 if (!interfaceClass.isInterface()) { 42 throw new IllegalArgumentException( 43 interfaceClass.getName() + " is not an interface"); 44 } 45 /* 46 * Verify that this interface is not a duplicate. 47 */ 48 if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { 49 throw new IllegalArgumentException( 50 "repeated interface: " + interfaceClass.getName()); 51 } 52 } 53 // package to define proxy class in 54 // 代理類的包名 55 String proxyPkg = null; 56 int accessFlags = Modifier.PUBLIC | Modifier.FINAL; 57 58 /* 59 * Record the package of a non-public proxy interface so that the 60 * proxy class will be defined in the same package. Verify that 61 * all non-public proxy interfaces are in the same package. 62 */ 63 for (Class<?> intf : interfaces) { 64 int flags = intf.getModifiers(); 65 if (!Modifier.isPublic(flags)) { 66 accessFlags = Modifier.FINAL; 67 String name = intf.getName(); 68 int n = name.lastIndexOf('.'); 69 String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); 70 if (proxyPkg == null) { 71 proxyPkg = pkg; 72 } else if (!pkg.equals(proxyPkg)) { 73 throw new IllegalArgumentException( 74 "non-public interfaces from different packages"); 75 } 76 } 77 } 78 79 if (proxyPkg == null) { 80 // if no non-public proxy interfaces, use com.sun.proxy package 81 proxyPkg = com.sun.proxy package 82 proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; 83 } 84 85 /* 86 * 生成代理類的類名 87 * Choose a name for the proxy class to generate. 88 */ 89 long num = nextUniqueNumber.getAndIncrement(); 90 String proxyName = proxyPkg + proxyClassNamePrefix + num; 91 92 /* 93 * Generate the specified proxy class. 94 */ 95 //生成代理類class文件 96 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags); 97 try { 98 // 返回代理類對象 99 return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); 100 } catch (ClassFormatError e) { 101 /* 102 * A ClassFormatError here means that (barring bugs in the 103 * proxy class generation code) there was some other 104 * invalid aspect of the arguments supplied to the proxy 105 * class creation (such as virtual machine limitations 106 * exceeded). 107 */ 108 throw new IllegalArgumentException(e.toString()); 109 } 110 } 111 } 112 }
在代碼的第96行,生成了代理類的class文件,而且在99行返回了咱們須要的代理類對象。那麼怎麼找到這個生成的代理類class文件呢?兩個步驟:
1,添加一行代碼:
//實例化調用處理類(編好的故事) MyStoryInvocationHandler handler = new MyStoryInvocationHandler(liHong); //添加這一句是生成代理類的class文件,前提是你須要在工程根目錄下建立com/sun/proxy目錄 System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
2,建立com/sun/proxy目錄:
當這個程序執行完以後就會有$Proxy0.class文件出現:
六,反編譯$Proxy0.class
1 package com.sun.proxy; 2 3 import com.zcz.proxyTest.testtwo.Singer; 4 import java.lang.reflect.InvocationHandler; 5 import java.lang.reflect.Method; 6 import java.lang.reflect.Proxy; 7 import java.lang.reflect.UndeclaredThrowableException; 8 9 //繼承了Proxy類,實現了Singer接口 10 public final class $Proxy0 extends Proxy implements Singer{ 11 private static Method m1; 12 private static Method m4; 13 private static Method m2; 14 private static Method m3; 15 private static Method m0; 16 17 //構造方法,直接調用了父類,也就是Proxy的構造方法,參數paramInvocationHandler就是咱們的MyStoryInvocationHandler實例化對象handler 18 public $Proxy0(InvocationHandler paramInvocationHandler)throws { 19 super(paramInvocationHandler); 20 } 21 22 public final boolean equals(Object paramObject) 23 throws { 24 try 25 { 26 return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue(); 27 } 28 catch (Error|RuntimeException localError) 29 { 30 throw localError; 31 } 32 catch (Throwable localThrowable) 33 { 34 throw new UndeclaredThrowableException(localThrowable); 35 } 36 } 37 38 //實現了sayGoodBye 39 public final void sayGoodBye(String paramString) 40 throws { 41 try 42 { 43 // 這裏的h就是咱們的MyStoryInvocationHandler實例化對象handler,緣由在下方解釋。 44 // 這裏直接調用了MyStoryInvocationHandler的invoke方法 45 this.h.invoke(this, m4, new Object[] { paramString }); 46 return; 47 } 48 catch (Error|RuntimeException localError) 49 { 50 throw localError; 51 } 52 catch (Throwable localThrowable) 53 { 54 throw new UndeclaredThrowableException(localThrowable); 55 } 56 } 57 58 public final String toString() 59 throws 60 { 61 try 62 { 63 return (String)this.h.invoke(this, m2, null); 64 } 65 catch (Error|RuntimeException localError) 66 { 67 throw localError; 68 } 69 catch (Throwable localThrowable) 70 { 71 throw new UndeclaredThrowableException(localThrowable); 72 } 73 } 74 //實現了orderSong方法 75 public final void orderSong(String paramString) 76 throws 77 { 78 try 79 { 80 // 這裏的h就是咱們的MyStoryInvocationHandler實例化對象handler,緣由在下方解釋。 81 // 這裏直接調用了MyStoryInvocationHandler的invoke方法 82 this.h.invoke(this, m3, new Object[] { paramString }); 83 return; 84 } 85 catch (Error|RuntimeException localError) 86 { 87 throw localError; 88 } 89 catch (Throwable localThrowable) 90 { 91 throw new UndeclaredThrowableException(localThrowable); 92 } 93 } 94 95 public final int hashCode() 96 throws 97 { 98 try 99 { 100 return ((Integer)this.h.invoke(this, m0, null)).intValue(); 101 } 102 catch (Error|RuntimeException localError) 103 { 104 throw localError; 105 } 106 catch (Throwable localThrowable) 107 { 108 throw new UndeclaredThrowableException(localThrowable); 109 } 110 } 111 112 //靜態代碼塊,作初始化操做 113 static 114 { 115 try 116 { 117 m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); 118 //經過反射,獲取sayGoodBye方法對象實例 119 m4 = Class.forName("com.zcz.proxyTest.testtwo.Singer").getMethod("sayGoodBye", new Class[] { Class.forName("java.lang.String") }); 120 m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); 121 //經過放射,獲取orderSong方法對象實例 122 m3 = Class.forName("com.zcz.proxyTest.testtwo.Singer").getMethod("orderSong", new Class[] { Class.forName("java.lang.String") }); 123 m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); 124 return; 125 } 126 catch (NoSuchMethodException localNoSuchMethodException) 127 { 128 throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); 129 } 130 catch (ClassNotFoundException localClassNotFoundException) 131 { 132 throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); 133 } 134 } 135 }
從第一條中,能夠得知,代理類實例化的代碼是:cons.newInstance(new Object[]{h})。這裏是經過反射調用代理類對象的構造方法,傳入了參數h(咱們的MyStoryInvocationHandler實例化對象handler)。
若是你想要更詳細的瞭解反射機制,請查閱:Java程序語言的後門-反射機制
這個構造方法,就是上述反編譯代碼裏的構造方法,而上述反編譯代碼裏的構造方法調用了Proxy類的構造方法,來看一下Proxy類的構造方法:
1 /** 2 * the invocation handler for this proxy instance. 3 * @serial 4 */ 5 protected InvocationHandler h; 6 private Proxy() { 7 } 8 protected Proxy(InvocationHandler h) { 9 Objects.requireNonNull(h); 10 this.h = h; 11 }
這裏將咱們傳入的handler直接賦值給了InvocationHandler h。上述反編譯代碼中的45行和82行使用的this.h 就是咱們傳入的handler。
因此proxy.orderSong("就是如今");方法在執行的時候會去調用MyStoryInvocationHandler類的invoke方法。
相關java設計模式的文章:
JAVA設計模式-單例模式(Singleton)線程安全與效率
原創不易,轉載請聲明出處:http://www.javashuo.com/article/p-vmiqkrlz-a.html