繼上一篇博客設(shè)計(jì)模式之代理模式學(xué)習(xí)之后http://blog.csdn.net/u014427391/article/details/75115928,本博客介紹JDK動(dòng)態(tài)代理的實(shí)現(xiàn)原理,學(xué)習(xí)一下JDK動(dòng)態(tài)代理的源碼。
Proxy類。該類即為動(dòng)態(tài)代理類,可以使用反編譯工具查看jdk里源碼。JDK動(dòng)態(tài)代理實(shí)現(xiàn)主要由Proxy類的newProxyInstance()方法實(shí)現(xiàn)。實(shí)現(xiàn)起來(lái)很容易,但是學(xué)習(xí)都要學(xué)習(xí)原理,所以本博客主要介紹jdk動(dòng)態(tài)代理實(shí)現(xiàn)的源碼。
newProxyInstance()方法用于根據(jù)傳入的接口類型interfaces返回一個(gè)動(dòng)態(tài)創(chuàng)建的代理類的實(shí)例,方法中第一個(gè)參數(shù)loader表示代理類的類加載器,第二個(gè)參數(shù)interfaces表示被代理類實(shí)現(xiàn)的接口列表,第三個(gè)參數(shù)h表示所指派的調(diào)用處理程序類。
首先寫個(gè)例子實(shí)現(xiàn)jdk動(dòng)態(tài)代理
主題接口類:
public interface IHello { public void sayHello(); }
被代理的類:
public class Hello implements IHello{ public void sayHello() { System.out.println("hello!"); } }
JDK動(dòng)態(tài)代理InvocationHandler類
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class MyInvocationHandler implements InvocationHandler { private Object target;//委托類 public MyInvocationHandler(Object target){ this.target=target; } @Override public Object invoke(Object o, Method method, Object[] args) throws Throwable { /**代理環(huán)繞**/ //執(zhí)行實(shí)際的方法 Object invoke = method.invoke(target, args); return invoke; } }
寫個(gè)類模擬字節(jié)碼文件生成:
import java.lang.reflect.Proxy;/** * Created by Nicky on 2017/7/20 0020. */public class Test { public static void main(String[] args){ System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); IHello ihello = (IHello) Proxy.newProxyInstance(IHello.class.getClassLoader(), //加載接口的類加載器 new Class[]{IHello.class}, //一組接口 new MyInvocationHandler(new Hello())); //自定義的InvocationHandler ihello.sayHello(); } }
實(shí)現(xiàn)jdk動(dòng)態(tài)代理是很容易的,不過(guò)現(xiàn)在介紹一下jdk源碼,理解一下原理實(shí)現(xiàn)
下面看一下Proxy類里的newProxyInstance方法
@CallerSensitive public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { Objects.requireNonNull(h); //對(duì)象的拷貝 final Class<?>[] intfs = interfaces.clone(); /* * 權(quán)限安全檢查 */ final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } /* * Look up or generate the designated proxy class. * (查找或生產(chǎn)指定的代理類。) */ Class<?> cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler. * (使用指定的調(diào)用處理程序調(diào)用它的構(gòu)造函數(shù)。) */ try { if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } //獲取代理類的構(gòu)造函數(shù) final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; /* * onstructor、Filed、Method都繼承自java.lang.reflect.AccessibleObject, * 訪問(wèn)非public的方法或者字段都會(huì)產(chǎn)生IllegalAccessException異常 */ if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true);//setAccessible()為true可以繞過(guò)默認(rèn)的權(quán)限檢查 return null; } }); } //根據(jù)代理類的構(gòu)造函數(shù)來(lái)創(chuàng)建代理對(duì)象 return cons.newInstance(new Object[]{h}); } catch (IllegalAccessException|InstantiationException e) { throw new InternalError(e.toString(), e); } catch (InvocationTargetException e) { Throwable t = e.getCause(); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new InternalError(t.toString(), t); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } }
從newProxyInstance方法可以看出,生產(chǎn)代理類是由getProxyClass0獲取或者生成的。下面看一下getProxyClass0方法,從方法可以看出如果緩存中有代理類就直接返回代理的副本,否就使用ProxyClassFactory創(chuàng)建代理類。
/** * Generate a proxy class. Must call the checkProxyAccess method * to perform permission checks before calling this. */ private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { //接口列表數(shù)目不能超過(guò)65535,因?yàn)樵赾lass文件中,這些個(gè)數(shù)都是用4位16進(jìn)制表示的,所以最大值是2的16次方-1 if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } // If the proxy class defined by the given loader implementing // the given interfaces exists, this will simply return the cached copy; // otherwise, it will create the proxy class via the ProxyClassFactory //如果緩存中有代理類就直接返回代理的副本,否就使用ProxyClassFactory創(chuàng)建代理類 return proxyClassCache.get(loader, interfaces); }
proxyClassCache是一個(gè)WeakCache類型的緩存,它的構(gòu)造函數(shù)有兩個(gè)參數(shù),其中一個(gè)就是用于生成代理類的ProxyClassFactory,看一下proxyClassCache.get方法的代碼:
public V get(K key, P parameter) { Objects.requireNonNull(parameter); //清理持有弱引用的WeakHashMap這種數(shù)據(jù)結(jié)構(gòu) expungeStaleEntries(); //從隊(duì)列中獲取cacheKey Object cacheKey = CacheKey.valueOf(key, refQueue); // lazily install the 2nd level valuesMap for the particular cacheKey //懶加載的方式封裝第二層valueMap,ConcurrentMap是一種線程安全的Map ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey); if (valuesMap == null) { ConcurrentMap<Object, Supplier<V>> oldValuesMap = map.putIfAbsent(cacheKey, valuesMap = new ConcurrentHashMap<>()); if (oldValuesMap != null) { valuesMap = oldValuesMap; } } // create subKey and retrieve the possible Supplier<V> stored by that // subKey from valuesMap Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); Supplier<V> supplier = valuesMap.get(subKey); Factory factory = null; while (true) { if (supplier != null) { // supplier might be a Factory or a CacheValue<V> instance //核心代碼,從supplier或者value,可能返回工廠實(shí)例或者Cache實(shí)例,返回實(shí)現(xiàn)InvokeHandler的類并包含了所需要的信息。 V value = supplier.get(); if (value != null) { return value; } } // else no supplier in cache // or a supplier that returned null (could be a cleared CacheValue // or a Factory that wasn't successful in installing the CacheValue) // lazily construct a Factory //懶加載方式構(gòu)建工廠實(shí)例 if (factory == null) { factory = new Factory(key, parameter, subKey, valuesMap); } /**填充supplier**/ if (supplier == null) { supplier = valuesMap.putIfAbsent(subKey, factory); if (supplier == null) { // successfully installed Factory supplier = factory; } // else retry with winning supplier } else { if (valuesMap.replace(subKey, supplier, factory)) { // successfully replaced // cleared CacheEntry / unsuccessful Factory // with our Factory supplier = factory; } else { // retry with current supplier supplier = valuesMap.get(subKey); } } } }
若緩存中找不到代理類,就使用ProxyClassFactory生產(chǎn)代理類,看一下ProxyClassFactory類的代碼:
/** * A factory function that generates, defines and returns the proxy class given * the ClassLoader and array of interfaces. */ private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>> { // prefix for all proxy class names(統(tǒng)一所以代理類的前綴名都以$Proxy開(kāi)始) private static final String proxyClassNamePrefix = "$Proxy"; // next number to use for generation of unique proxy class names //給每個(gè)代理類名加個(gè)唯一的編號(hào),如$Proxy0,$Proxy1等等 private static final AtomicLong nextUniqueNumber = new AtomicLong(); @Override public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); for (Class<?> intf : interfaces) { /* * Verify that the class loader resolves the name of this * interface to the same Class object. */ Class<?> interfaceClass = null; //通過(guò)類名加載每一個(gè)接口運(yùn)行時(shí)的信息 try { interfaceClass = Class.forName(intf.getName(), false, loader); } catch (ClassNotFoundException e) { } //驗(yàn)證使用classLoad加載的類與傳入的類是否相同 if (interfaceClass != intf) { throw new IllegalArgumentException( intf + " is not visible from class loader"); } /* * Verify that the Class object actually represents an * interface. * 驗(yàn)證傳入的是否為接口類型,因?yàn)閖dk動(dòng)態(tài)代理只支持接口類型 */ if (!interfaceClass.isInterface()) { throw new IllegalArgumentException( interfaceClass.getName() + " is not an interface"); } /* * Verify that this interface is not a duplicate. * 驗(yàn)證接口是否重復(fù) */ if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } } String proxyPkg = null; // package to define proxy class in int accessFlags = Modifier.PUBLIC | Modifier.FINAL; /* http://www.cnblogs.com/mzq123/p/7215966.html