摘要:用戶在調(diào)用被動態(tài)代理過的對象的方法時,調(diào)用的請求會被自動發(fā)給代理對象實現(xiàn)了接口的方法,由方法來實現(xiàn)對請求的統(tǒng)一處理。動態(tài)代理實現(xiàn)切面代替該語句塊一定會在前面執(zhí)行。
用戶在調(diào)用被動態(tài)代理過的對象的方法時,調(diào)用的請求會被自動發(fā)給代理對象(實現(xiàn)了InvocationHandler接口)的invoke()方法,由invoke()方法來實現(xiàn)對請求的統(tǒng)一處理。
源碼分析Java.lang.reflect.Proxy
public class Proxy implements java.io.Serializable { private static final Class>[] constructorParams = { InvocationHandler.class }; private static final WeakCache[], Class>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory()); ...... @CallerSensitive 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); } //生成代理類的class Class> cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler. */ try { if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } //getConstructor(InvocationHandler.class) 獲取代理類的構(gòu)造器 final Constructor> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction () { public Void run() { cons.setAccessible(true); return null; } }); } //代理類實例化返回 return cons.newInstance(new Object[]{h}); } ...... } private static Class> getProxyClass0(ClassLoader loader, Class>... interfaces) { if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } // key為WeakReference,若緩存中存在相同key,則返回ProxyClass,若不存在,則用ProxyClassFactory創(chuàng)建ProxyClass。 return proxyClassCache.get(loader, interfaces); //java.lang.reflect.WeakCache 這個內(nèi)核分析? } ...... }
private static final class ProxyClassFactory implements BiFunction$Proxy.class[], Class>> { //?所有代理類ProxyClass名字的前綴? private static final String proxyClassNamePrefix = "$Proxy"; // 用計數(shù)器生成代理類ProxyClass的名字 private static final AtomicLong nextUniqueNumber = new AtomicLong(); @Override public Class> apply(ClassLoader loader, Class>[] interfaces) { Map , Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); //對每一個interface Class進行驗證 for (Class> intf : interfaces) { /* * Verify that the class loader resolves the name of this * interface to the same Class object. */ Class> interfaceClass = null; try { interfaceClass = Class.forName(intf.getName(), false, loader); } catch (ClassNotFoundException e) { } if (interfaceClass != intf) { throw new IllegalArgumentException( intf + " is not visible from class loader"); } /* * Verify that the Class object actually represents an * interface. */ if (!interfaceClass.isInterface()) { throw new IllegalArgumentException( interfaceClass.getName() + " is not an interface"); } /* * Verify that this interface is not a duplicate. * 用IdentityHashMap來驗證interface Class的唯一性,因為IdentityHashMap的key比較是==,即比較內(nèi)存地址。 */ if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } } String proxyPkg = null; int accessFlags = Modifier.PUBLIC | Modifier.FINAL; // 對于非公共接口,ProxyClass的包名設(shè)置為接口的包名?? 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"); } } } //?對于公共接口,ProxyClass的包名為com.sun.proxy?? if (proxyPkg == null) { proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } long num = nextUniqueNumber.getAndIncrement(); //ProxyClass的完全限定名 String proxyName = proxyPkg + proxyClassNamePrefix + num; //由c++寫的ProxyGenerator生成代理類的二進制字節(jié)碼 byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); try { //?根據(jù)二進制字節(jié)碼返回相應(yīng)的ProxyClass?? return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { throw new IllegalArgumentException(e.toString()); } } }
以下是反編譯$Proxy0.class:
public?final?class?$Proxy0?extends?Proxy?implements?MyInterface1{?? ??private?static?Method?m1;?? ??private?static?Method?m3;?? ??private?static?Method?m0;?? ??private?static?Method?m2;?? ? ??public?$Proxy0(InvocationHandler?paramInvocationHandler)?{?? ????super(paramInvocationHandler);?? ??}?? ?? ??public?final?boolean?equals(Object?paramObject)?{?? ????try?{?? ??????return?((Boolean)this.h.invoke(this,?m1,?new?Object[]?{?paramObject?})).booleanValue();?? ????}?? ????catch?(Error|RuntimeException?localError)?{?? ??????throw?localError;?? ????}?? ????catch?(Throwable?localThrowable)?{?? ??????throw?new?UndeclaredThrowableException(localThrowable);?? ????}?? ??}?? ?? ??public?final?void?sayHello(String?paramString)?{?? ????try?{?? ??????this.h.invoke(this,?m3,?new?Object[]?{?paramString?});?? ??????return;?? ????}?? ????catch?(Error|RuntimeException?localError)?{?? ??????throw?localError;?? ????}?? ???catch?(Throwable?localThrowable)?{?? ??????throw?new?UndeclaredThrowableException(localThrowable);?? ????}?? ??}?? ?? ??public?final?int?hashCode()?{?? ????try?{?? ??????return?((Integer)this.h.invoke(this,?m0,?null)).intValue();?? ????}?? ????catch?(Error|RuntimeException?localError)?{?? ??????throw?localError;?? ????}?? ????catch?(Throwable?localThrowable)?{?? ??????throw?new?UndeclaredThrowableException(localThrowable);?? ????}?? ??}?? ?? ??public?final?String?toString()?{?? ????try?{?? ???? return?(String)this.h.invoke(this,?m2,?null);?? ????}?? ????catch?(Error|RuntimeException?localError)?{?? ??????throw?localError;?? ????}?? ????catch?(Throwable?localThrowable)?{?? ??????throw?new?UndeclaredThrowableException(localThrowable);?? ????}?? ??}?? ?? ??static?{?? ????try?{?? ??????m1?=?Class.forName("java.lang.Object").getMethod("equals",?new?Class[]?{?Class.forName("java.lang.Object")?});?? ??????m3?=?Class.forName("com.mikan.proxy.MyInterface1").getMethod("sayHello",?new?Class[]?{?Class.forName("java.lang.String")?});?? ??????m0?=?Class.forName("java.lang.Object").getMethod("hashCode",?new?Class[0]);?? ????m2?=?Class.forName("java.lang.Object").getMethod("toString",?new?Class[0]);?? ??????return;?? ????}?? ????catch?(NoSuchMethodException?localNoSuchMethodException)?{?? ??????throw?new?NoSuchMethodError(localNoSuchMethodException.getMessage());????}?? ????catch?(ClassNotFoundException?localClassNotFoundException)?{?? ??????throw?new?NoClassDefFoundError(localClassNotFoundException.getMessage());?? ????}?? ??}?? }?
?
$Proxy0.class的總結(jié):
對于要代理沒有接口的類,則必須繼承該沒有接口的類,從而覆蓋其方法,但由于java不能多繼承,這里代理類已經(jīng)繼承了Proxy類了,不能再繼承其他的類,所以JDK的動態(tài)代理不支持對實現(xiàn)類的代理,只支持接口的代理。
構(gòu)造方法的入?yún)镮nvocationHandler,這說明該代理類是實現(xiàn)了InvocationHandler接口的類的代理類,而InvocationHandler實現(xiàn)類再代理真正的實體類。
靜態(tài)代碼塊會初始化真正實體類的Method對象,以及Object類的equals、hashCode、toString的Method對象。
總結(jié):
Proxy 會從內(nèi)部類WeakCache中根據(jù)ClassLoader 和interfaces獲取ProxyClass(若緩存中存在相同key,則返回ProxyClass,若不存在,則用ProxyClassFactory創(chuàng)建ProxyClass(由ProxyGenerator生成二進制碼,再將寫成*.class文件))。
切面InvocationHandler:
public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?throws?Throwable?{?? ????//?BeforeAdvice?? ????Object?retVal?=?null;?? ????try?{?? ????????retVal?=?method.invoke(target,?args);??//?AroundAdvice?代替該語句????? ????????//?AfterReturningAdvice?? ????}?? ????catch?(Throwable?e)?{?? ????????//?AfterThrowingAdvice?? ????}?? ????finally?{?? ???? //finally塊一定會在return前面執(zhí)行。 ????????//?AfterAdvice?? ????}?? ????return?retVal;?? }??
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/67267.html
摘要:要明白,動態(tài)代理類的存在意義是為了攔截方法并修改邏輯而動態(tài)代理的局限性之一就是只能攔截接口所聲明的方法。因為動態(tài)代理類是繼承自業(yè)務(wù)類,所以該類和方法不能聲明成無法繼承或重寫。者最終都是生成了一個新的動態(tài)代理類對象。 動態(tài)代理 1、先談靜態(tài)代理 對于靜態(tài)代理,我們已經(jīng)很熟悉了。我們擁有一個抽象類,真實類繼承自抽象類并重寫其業(yè)務(wù)方法,代理類持有真實類的對象實例,在重寫業(yè)務(wù)方法中通過調(diào)用真實...
摘要:動態(tài)代理的核心是接口和類。以上結(jié)果說明它生成的代理類為,說明是代理。測試前提實現(xiàn)接口測試類使用接口方式注入代理方式必須以接口方式注入測試配置為,運行結(jié)果如下實際校驗邏輯。。。。 本文也同步發(fā)布至簡書,地址:https://www.jianshu.com/p/f70... AOP設(shè)計模式通常運用在日志,校驗等業(yè)務(wù)場景,本文將簡單介紹基于Spring的AOP代理模式的運用。 1. 代理模...
摘要:與靜態(tài)代理對比,動態(tài)代理是在動態(tài)生成代理類,由代理類完成對具體方法的封裝,實現(xiàn)的功能。本文將分析中兩種動態(tài)代理的實現(xiàn)方式,和,比較它們的異同。那如何動態(tài)編譯呢你可以使用,這是一個封裝了的庫,幫助你方便地實現(xiàn)動態(tài)編譯源代碼。 發(fā)現(xiàn)Java面試很喜歡問Spring AOP怎么實現(xiàn)的之類的問題,所以寫一篇文章來整理一下。關(guān)于AOP和代理模式的概念這里并不做贅述,而是直奔主題,即AOP的實現(xiàn)方...
摘要:值得一提的是由于采用動態(tài)創(chuàng)建子類的方式生成代理對象,所以不能對目標類中的方法進行代理。動態(tài)代理中生成的代理類是子類,調(diào)試的時候可以看到,打開源碼可看到實現(xiàn)了和也就實現(xiàn)方法。 前面講到了動態(tài)代理的底層原理,接下來我們來看一下aop的動態(tài)代理.Spring AOP使用了兩種代理機制:一種是基于JDK的動態(tài)代理,一種是基于CGLib的動態(tài)代理. ①JDK動態(tài)代理:使用JDK創(chuàng)建代理有一個限制...
摘要:實際開發(fā)中的,通用異常處理,通用日志處理,事物處理都可以用到動態(tài)代理。四總結(jié)優(yōu)點動態(tài)代理類簡化了代碼編程工作,提高了軟件的可擴展性。 JDK的動態(tài)代理 一、靜態(tài)代理 了解動態(tài)代理前,有必要先講解下靜態(tài)代理。 舉個例子:銀行開通了短信業(yè)務(wù),在你取錢,存錢,轉(zhuǎn)賬后都會 給你發(fā)送短信,我們來模擬下業(yè)務(wù)場景。 靜態(tài)代理的實現(xiàn) 下面來模擬下業(yè)務(wù)代碼 1.定義IBankCardService接口 ...
摘要:動態(tài)代理是包提供的方式,它必須借助一個接口才能產(chǎn)生代理對象,所以要預(yù)先定義接口。第步,建立代理對象和真實對象的關(guān)系。第個是把生成的動態(tài)代理對象下掛在哪些接口下,這個寫法就是放在實現(xiàn)的接口下。 JDK動態(tài)代理是java.lang.reflect.*包提供的方式,它必須借助一個接口才能產(chǎn)生代理對象,所以要預(yù)先定義接口。 1. 接口 public interface Hello { ...
閱讀 3410·2021-09-22 15:01
閱讀 535·2019-08-30 11:11
閱讀 971·2019-08-29 16:17
閱讀 1219·2019-08-29 12:23
閱讀 2036·2019-08-26 11:48
閱讀 3190·2019-08-26 11:48
閱讀 1429·2019-08-26 10:33
閱讀 1939·2019-08-26 10:30