建立代理類接口java
public interface ProxyInterface { public String proxy(String username); }
建立接口的實現緩存
public class ProxyClass implements ProxyInterface { public String proxy(String username) { System.out.println("....processor...."); return String.format("Hello Proxy : %s", username); } }
實現一個InvocationHandlerapp
public class ProxyInvocationHandler implements InvocationHandler { private Object target; public ProxyInvocationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("---Before---Method Name:" + method.getName()); Object retVal = method.invoke(target, args); System.out.println("---After---Return Value:" + retVal); return retVal; } }
使用動態代理執行被代理類的方法ide
public class Main { public static void main(String[] args) { ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler(new ProxyClass()); ProxyInterface proxy = (ProxyInterface) Proxy.newProxyInstance(Main.class.getClassLoader(), new Class[]{ProxyInterface.class}, proxyInvocationHandler); proxy.proxy("sage"); } }
查看輸出結果函數
---Before---Method Name:proxy ....processor.... ---After---Return Value:Hello Proxy : sage
咱們從上面的代碼能夠看出,JDK動態代理的使用很是簡單,只須要調用Proxy.newProxyInstance方法便可,咱們就從這裏入手看一下JDK動態代理的源碼實現.下面的代碼,沒有特殊說明,都是在Proxy類中~性能
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { Objects.requireNonNull(h); final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } /* * 查找或生成動態代理類.(JDK若是在緩存中已經找到生成的動態代理類,會直接返回) */ Class<?> cl = getProxyClass0(loader, intfs); /* * 使用咱們的InvocationHandler做爲新生成的代理類的構造方法的參數,來獲取代理類的實例 */ try { if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true); return null; } }); } 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); } }
在這裏最重要的地方就是註釋的兩個地方:ui
private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { //檢查被代理類的接口數量,不能多於65535,問題是...誰會寫那麼多接口... if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } //JDK對生成的動態代理類進行了緩存,若是已經存在了相應的代理類,就直接返回,提升了性能 return proxyClassCache.get(loader, interfaces); }
下面咱們來看一下proxyClassCache,具體的緩存方式我就不詳說了,就來看一下這個proxyClassCache是如何建立的吧,這裏有一個很重要的東西.this
private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
這裏面使用了ProxyClassFactory來生成代理類,咱們來看一下這個類的源碼:ProxyClassFactory是Proxy的靜態內部類.spa
private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>> { // 全部動態代理類的前綴都以 $Proxy 開頭 private static final String proxyClassNamePrefix = "$Proxy"; // 用於生成代理類名字的計數器,也就是說,全部代理類的名字模式都同樣,使用計數器來分別 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. */ } //代理類的包名 String proxyPkg = null; int accessFlags = Modifier.PUBLIC | Modifier.FINAL; //若是接口不是public的,那麼生成代理類的包名和被代理類的包名相同 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"); } } } //若是在上面的邏輯中沒有設置生成代理類的包名,則指定默認值:com.sun.proxy. if (proxyPkg == null) { // if no non-public proxy interfaces, use com.sun.proxy package proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } //計數器增長,生成代理類的類名 long num = nextUniqueNumber.getAndIncrement(); String proxyName = proxyPkg + proxyClassNamePrefix + num; //生成代理類的核心邏輯,這段代碼木有開源,咱們一下子能夠反編譯看一下大概的內容 byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); try { return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { /* * A ClassFormatError here means that (barring bugs in the * proxy class generation code) there was some other * invalid aspect of the arguments supplied to the proxy * class creation (such as virtual machine limitations * exceeded). */ throw new IllegalArgumentException(e.toString()); } } }
由於這個類是沒有開源的,因此咱們就大體來看一下這個方法的內容:代理
public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) { ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2); final byte[] var4 = var3.generateClassFile(); 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), new String[0]); Files.createDirectories(var3, new FileAttribute[0]); var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class"); } else { var2 = Paths.get(var0 + ".class", new String[0]); } Files.write(var2, var4, new OpenOption[0]); return null; } catch (IOException var4x) { throw new InternalError("I/O exception saving generated file: " + var4x); } } }); } return var4; }
saveGeneratedFiles:來判斷是否將生成的動態代理類保存到本地的變量,是經過環境變量來判斷的的.
sun.misc.ProxyGenerator.saveGeneratedFiles
還使用最開始的例子, 先在main方法的最開始配置環境變量:
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
運行Main方法,而後進入com/sun/proxy包,查看一下生成的代理類:
public final class $Proxy0 extends Proxy implements ProxyInterface { private static Method m1; private static Method m2; private static Method m3; private static Method m0; public $Proxy0(InvocationHandler var1) throws { super(var1);//就是將InvocationHandler賦值給Proxy的h變量 } public final boolean equals(Object var1) throws { try { return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue(); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final String proxy(String var1) throws { try { return (String)super.h.invoke(this, m3, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final int hashCode() throws { try { return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue(); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")}); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m3 = Class.forName("test.sage.proxy.ProxyInterface").getMethod("proxy", new Class[]{Class.forName("java.lang.String")}); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } }
觀察這個類的特色以下:
經過上面的解析,咱們能夠總結出來: