JDK动态代理的底层实现原理_第1页
JDK动态代理的底层实现原理_第2页
JDK动态代理的底层实现原理_第3页
JDK动态代理的底层实现原理_第4页
JDK动态代理的底层实现原理_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、JDK动态代理的底层实现原理动态代理是许多框架底层实现的基础,比方Spirng的AOP等,其实弄清 楚了动态代理的实现原理,它就没那么神奇了,下面就来通过案例和分析JDK 底层源码来揭秘她的神秘面纱,让她一丝不挂地呈现在我们面前,邪恶 了 O O O代理模式定义存在一个代理对象,并且这个代理对象持有真实对象的引用,以实现对真实对 象的访问控制。举个例子,现在公司一般都有V*,使我们在家也能访问到公司的内网(比方 连接公司的数据库等),实现居家办公。这里V*相当于一个代理,而公司内 网相当于被代理对象,也就是真实对象。我们不能直接访问公司内网(真实对 象),但是我们通过V* (代理对象),输入身

2、份信息,确认无误后就可以访 问到公司内网。这就是代理模式的作用一一控制对象的访问。代理模式的分类静态代理该代理对象持有被代理对象的引用,客户端通过调用代理对象的方法间接实现 调用真实对象的方法。代理对象可以在调用真实对象的方法前面加入一些操 作:比方身份验证,如果身份验证没有通过,那么不能访问真实对象的方法,否Proxy./7eki/?r(9Ay/77s/7ce(this.getClass().getClassLoader()ztarget.getClass( ).getlnterfaces(),this);看看JDK的底层实现:publics etMt io ObjectCla*aljoad

3、rClarstl intrtace#threw tX;*galxgunntxcpxonh = null) throw tww MuXlPanrExcapcionO r生成代理类C1au d gOJryCLAMloada” faces ty Constructor cons = cl.atContFuctr( natch fHfclUchM*thodExcption I throw now Intetfialltror(.towering()/) jtch (Ill XAccBExcepVion ) I tbrow nmr Xnt*malXrxor01;) catch (Instantiatia

4、nKxcepion )(贴出代码,去掉了异常和判断public static Object newProxylnstance(ClassLoader loader,Class interfaces,TnvocationHand1er h)throws IllegalArgumentExceptionClass cl = getProxyClass(loader, interfaces);/ Class constructorParams = InvocationHandler. class ;Constructor cons 二 cl.getConstructor (constructorPa

5、rams);return cons, newlnstance(new Object h ); 通过源码可以知道,生成代理类是通过如下方法实现的:Class cl = getProxyC/assoader, interfaces);再追踪一下,这个方法里面内容很多,但是最关键的就是下面这个方法:byte proxyClassFile = ProxyGeneratox.generateProxyClassproxyName, interfaces);通过这个方法就生成了代理类的字节码,只不过调用完就不存在了。所以我们 看不到它的源码。我们也可以模拟生成代理类,看看生成的动态代理类到底是个什么东西通

6、过如下类就可以生成代理类的字节码/* *GenerateDynamic*生成代理类字节码的类*author: tanggao*date: : 2017-9-27 下午 5:36:54*version 1. 0*/public class GenerateDynamic public static void main(String args) /* People p = new Student ();DynamicProxyHand1er handler = new DynamicProxyHandler();People proxy 二(People) Proxy. newProxylnsta

7、nce(handler. getClassO .getClassLoader(), p. getClass(). getlnterfaces(), handler);proxy. sayBye (/,tanggao,/)产/createProxyClassFile 0;private static void createProxyClassFile() String name = ProxySubject;byte data = ProxyGenerator. generateProxyClass(name, new Class People, class );FileOutputStream

8、 out = null;try (out = new FileOutputStream(name + class);System. out. println(new File(hello) getAbsolutePath();out. write(data); catch (FileNotFoundException e) e. printStackTrace (); catch (lOException e) e. printStackTrace ();finally if (null != out)try out. close (); catch (lOException e) e. pr

9、intStackTrace ();)用反编译工具查看一下生成的字节码,先上代码,后面再分析:import com. dynamic, test. People;import java. lang. reflect. Invocationllandler;import java. lang, reflect. Method;import java. lang, reflect. Proxy;import java. lang, reflect. UndeclaredThrowableException;public final class ProxySubject extends Proxy i

10、mplements Peopleprivatestatic Method ml;privatestatic Method m3;private static Method m4;private static Method mO;private static Method m2;public ProxySubject(InvocationHandler paramlnvocationHandler) throws(super (paramlnvocationHandler);public final boolean equals(Object paramObject) throws(try(re

11、turn (Boolean)this. h. invoke(this, ml, new Object paramObject ). b ooleanValue();catch (Error|RuntimeException localError)(throw localError;)catch (Throwable localThrowable)(throw new UndeclaredThrowableException(localThrowable);public final void sayBye(String paramString)throws(try(this. h. invoke

12、 (this, m3, new Object paramString ); return;catch (Error|RuntimeException localError)throw localError;catch (Throwable localThrowable)throw new UndeclaredThrowableException(localThrowable);public final void sayllello(String paramString) throws(try(this. h. invoke (this, m4, new Object paramString )

13、; return;catch (Error|RuntimeException localError)throw localError;)catch (Throwable localThrowable)throw new UndeclaredThrowableException(localThrowable);public final int hashCode()throwstryreturn (Integer)this. h. invoke(this, mO, null). intValue();catch (Error|RuntimeException localError)(throw l

14、ocalError;)catch (Throwable localThrowable)(throw new UndeclaredThrowableException(localThrowable);)public final String toStringOthrows(tryreturn (String)this. h. invoke(this, m2, null);)catch (Error|RuntimeException localError)throw localError;)catch (Throwable localThrowable)throw new UndeclaredTh

15、rowableException(localThrowable);statictry(ml 二 Class. forName(zzjava. lang. Object/7). getMethod(zzequalsz,, new Class Class. forName (,zjava. lang. Object) );m3 = Class. forName (zzcom. dynamic, test. People,z). getMethod (z,sayByez/, new Cla ss Class. forName (z,java. lang. String) );m4 = Class.

16、forName (/zcom. dynamic, test. Peoplez,). getMethod(/zsayHello/z, new C lass Class. forName (z,java. lang. String7?) );mO = Class. forName(/zjava. lang. Object). getMethod(/zhashCodez,, new Class 0);m2 二 Class. forName (zz java. lang. Objectz,). getMethod (/ztoString/,, new Class M);return;catch (No

17、SuchMethodException localNoSuchMethodException)throw new NoSuchMethodError(localNoSuchMethodException. getMessage();catch (ClassNotFoundException localClassNotFoundException)(throw new NoClassDefFoundError(localClassNotFoundException. getMessage();)分析过程直接看图:就是调用 ProxygvProxyg5tance(thk.gex?xy5Qbx-C

18、(ZzvscauctdUDlIir th SIHpn”s stAtie prlvtU autie pflTU tUUfi privite sutic2U, foul PUaa eauAliiOtct xtaXectJpublicObject mtwFroaylnsVafice(ClotLestiot lodax9Xavocai xmBAfiaia rthrow XllgalAr9uiaantNCpi.i6n Xooi 9 et8:exyCi,itox”.Rti幺go dsRtteSs y,a, d- - J *: 一417.tty iCQut.rucEcx cons * eketCocuitx

19、ucrcor (twtum ccnv.ftew:natanclrww Ob5act11 I h li I OAtcii |3UJiefeMetiiodteweXea |ut*urFAl ffCaM(*)*4|i-w n”“j fdE.tmw*4MF*1 i.ottmuMr*M4Ee4a - 3“lt|“aj dj田毋unrt*;* cuMt&li;*VtWB4th板h欧里构通方法联用的用处与播cag |lst pKilir !Uia1 elA Frsryifcject eitoiMis Fruxr glmi” 加平;.kleeallnccjEE nikTmBU 8oc3Errwcm所以可以看到

20、生成的动态代理类其实跟静态代理类还是有区别的,静态代理是 我们直接控制真实对象的方法调用,而动态代理是通过调用处理器的invoke方法来调用真实对象的方法,而这个invoke方法就是我们自己覆写的方法 t M I . J Q f thnamcpToxyXarMUar InrAC4*.icniiAnlx Ilirivate l*wop:. phlItfwyiutxdle t (I 7_ ,看 gCleK pev AppSodo。 C:Fvofam Ret U86KM*bAX7Q.OH*mimi0 Q017Q27 下 JQ:Hcillo tangg4o比看由诩日寺ByeBye tanggao啊日聿

21、上面就是静态代理的一个实现,通过静态代理,实现了访问控制,但是在每个 真实对象方法之前都加入了访问控制代码来验证权限。如果有很多个方法,那么 要在每个方法调用前都加入验证权限的代码,这样非常的不灵活且有大量的重 复代码,即使把验证权限抽象出来做过方法或者类,但是还是得在每个方法前 加一段调用权限验证的代码,比方,一个客户端只用其中的一个方法,但是代 理中两个方法都要加入权限控制,要满足其他客户端的调用需求,上面接口中 只有两个方法还好,但是如果有上百个方法那岂不是很臃肿。那么有什么方法 解决了,那就是动态代理动态代理动态的生成代理类,而不用像静态代理一样,在编译期间进行定义类。动态 代理更加灵

22、活,不用显示的在所有方法前面或者后面加入权限验证、记录日志 等操作。动态代理的实现如下:其中真实对象接口和它的实现跟静态代理是一样的。不同的是代理类的创立,静态代理是直接新增一个代理类,而动态代理那么不 是。动态代理是通过JDK的Proxy和一个调用处理器InvocationHandler来 实现的,通过Proxy来生成代理类实例,而这个代理实例通过调用处理器 InvocationHandler接收不同的参数灵活调用真实对象的方法。所以我们需要做的是创立调用处理器,该调用处理器必须实现JDK的 InvocationHandler/*DynamicProxyHandler*调用处理器实现动态代理

23、必不可少的组件*author: tanggao*date: : 2017-9-27 下午 5:08:49*version 1.0*/public class DynamicProxyHandler implements InvocationHandler private People target;public DynamicProxyHandler() this. target=new Student (); 实例化一个真实对象Overridepublic Object invoke (Object proxy, Method method, Object args)throws Throw

24、able boolean friendFlag=true;Object o=null;if(friendFlag) 权限验证通过所有方法的权限验证只需要在这里加代码就行了o = method. invoke(target, args);)System. out. printin (t己录访问 日 志);return o;/*通过Proxy动态生成一个代理实例*return*author:tanggaodate:2017-9-27 下午 4:57:07*return:Object/public Object getProxy() /*Proxy. newProxylnstance(ClassLo

25、ader loader, Class interfaces, In vocationllandler h)方法的第一个参数的作用就是获取当前类的类加载器,作用是用来生成类的第二个参数是获取真实对象的所有接口获取所有接口的目的是用来生成代理的,因为代理要实现所有的接口第三个参数是调用处理器 这里传入调用处理器,是因为生成代理实例需要 调用处理器为什么需要调用处理器,因为生成的代理不能直接调用真实对象的方法,而是通过调用处理器来调用真实对象的方法,具体就是通过上面定义的Dynam icProxyHandler 重写父类 InvocationHand 1 er 的 invoke 方法return Proxy. newProxyInstance(this. getClass(). getClassLoader(), target. getClass(). getlnterfaces(), this );代码解释:方法:Proxy.newProxyInstance(ClassLoacler loa

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论