JAVA设计模式-动态代理(Proxy)源码分析
在文章:JAVA设计模式-动态代理(Proxy)示例及说明中,为动态代理设计模式举了一个小小的例子,那么这篇文章就来分析一下源码的实现。
一,Proxy.newProxyInstance方法
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方法
二,Proxy.getProxyClass0方法
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缓存中读取的,来看一下这个缓存的声明:
//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)线程安全与效率
原创不易,转载请声明出处:https://www.cnblogs.com/zhangchengzi/p/9713807.html
才疏学浅,如有错误,欢迎大家留言评论。
如果大家觉得我的文章写的不错,“关注我”或者“推荐一下”吧,我会继续努力写出更好的文章。
觉得哪里写的不好的,可以留言或者加我微信告诉我。
另外我建立一个技术讨论群,欢迎大家来学习探讨,微信:fcg606808。