java静态代理和动态代理的原理分析与区别

更新时间:2023-05-06 15:42:16 阅读: 评论:0

简单总结⼀下java中的代理:
我的项⽬⾥需要调⽤⽬标类的⽅法时,不直接通过这个类的对象进⾏调⽤,⽽是通过⼀个代理类的对象来调⽤,即通过代理对象来访问⽬标对象,从⽽调⽤⽬标对象的⽅法;
2、为什么需要代理?使⽤代理有什么好处?
根据上⾯讲述的通过proxyA.doIt()来调⽤a.doIt(),这样做似乎没有什么⽤处呀。
确实,如果只是这样纯粹地代理⼀下,那多定义⼀个这样的代理类确实是不划算,它把调⽤关系复杂化了:项⽬代码-->proxy.doIt()-->a.doIt(),⽽不使⽤代理层的话,其调⽤关系则⽐较简单:项⽬代码-->a.doIt();
那我们为什么还要使⽤代理呢?原因可能是多样的,我这⾥根据我接触过的场景列举⼀些:
1)代理类可以对⽬标类的⽅法功能进⾏补充,即可以在调⽤⽬标类⽅法的前后做⼀些操作。什么意思呢?
假如现在⽬标类有个⽅法的作⽤是计算员⼯的税后⼯资,但是在计算税后⼯资之前我们希望记录⼀下当前正在计算哪个员⼯的税后⼯资;
这属于在调⽤⽬标类的⽅法之前做⼀些额外的补充操作;
还有在⼀种情况是调⽤了⽬标类的计算税后⼯资⽅法之后,考虑到可能有些员⼯会有旷⼯现象,需要对有旷⼯情况的员⼯进⾏罚款,所以调⽤了⽬标类的计算税后⼯资⽅法后,得到员⼯⼯资,判断⼀下员⼯是否有旷⼯现象,如果有的话在计算得到的税后⼯资基础上扣钱;
这就是属于在调⽤⽬标类的⽅法后做的额外操作,以满⾜业务场景需求。
2)计算⽬标类的⽅法调⽤的耗时;
有些场景下可能需要监控⽅法的调⽤耗时,并把它们输出到⽇志中,便于后续排查问题;
例如涉及到数据上传、下载的⽅法,有些后上传或者下载慢了,可能需要知道它们的执⾏情况,这时就可以统计⼀下这些⽅法调⽤的耗时,并输出到⽇志,如果出现慢的情况,可以通过⽇志查看⽅法的调⽤耗时是否合理;
针对这种场景,我们就需要在代理类中调⽤⽬标类的⽅法之前先获取⼀下当前时间,然后调⽤⽬标类的⽅法,当⽬标类的⽅法执⾏结束后,再计算出执⾏所花的时间。
3)有些⼈可能会疑问了,这些操作我放在⽬标类的⽅法⾥⾯做不⾏吗?为什么⾮得通过代理来做?
当然,其实不⽤代理实现也是可以的,起码相同的功能不⽤代理它也是可以实现的;
但是我们技术⼈不应该对⾃我要求仅仅停留在仅实现功能的层⾯上,我们追逐代码的通⽤性、简洁性、灵活性、低耦合等,提⾼代码的质量;
以计算税后⼯资的例⼦来说,如果我们把打印计算薪资的⽇志、计算旷⼯罚款等操作⼀股脑地都放在了计算税后⼯资的⽅法⾥,假设我们的场景是这样的:
有些地⽅需要获取税后⼯资减去旷⼯扣款,⽽有些地⽅仅需要获取税后⼯资,那我们的计算税后⼯资⽅法就没法兼容这两种场景了;
但是如果使⽤代理模式的话,需要获取税后⼯资减去旷⼯扣款的场景则通过代理对象获取,⽽只是纯粹获取税后⼯资的则直接调⽤⽬标类的计算税后⼯资⽅法获取;
我们引⼊代理后,则可以做到兼容这两种场景,需要代理的地⽅才使⽤代理对象,否则我们就直接调⽤⽬标类对象。
3、java是如何实现代理的?
java中的代理分为静态代理、动态代理和CGLIB代理。
代理模式:
java中的代理模式是指代码不直接访问⽬标对象,⽽是通过⼀个代理对象来访问⽬标对象,代理对象充当⼀个中介作⽤。
不管哪种代理⽅式,我们最终都需要获取到代理类的对象实例,根据获取代理信息的不同可分为静态代理和动态代理。
静态代理:
1)静态代理是指 在jvm运⾏之前就已经获取到代理类的class信息。这怎么理解呢?
在静态代理模式下,代理类需要开发者⾃⼰写好,即开发者需要⾃⼰实现代理类的.java⽂件,也就是说在项⽬编译之前就需要存在代理类的.java
运⾏结果
静态代理总结:
1)代理类的信息在jvm运⾏之前就已经⽣成,逻辑由开发者实现;
2)代理类与⽬标类的定义应该严格参照规范,定义公共接⼝并实现它,需要代理的⽅法在接⼝中都要定义好;
3. 静态代理原理:在代理类中包含⼀个⽬标类的对象引⽤,然后在使⽤时创建⼀个⽬标类对象并且创建⼀个代理类对象,并把⽬标类对象传给代
理类对象,然后将它赋予代理类中的⽬标类对象引⽤,
然后代理类所代理的⽅法中通过其所包含的⽬标类对象引⽤调⽤⽬标类的⽅法,从⽽实现通过代理调⽤⽬标类⽅法的效果。
静态代理的调⽤关系
动态代理:
1)动态代理是指 在java程序运⾏过程(程序已经启动在运⾏了)由jvm⽣成代理类的class信息,该class信息⽣成后是直接处于内存中的,并没有写⼊磁盘保存起来;
然后通过反射⽅式实例化代理类对象,因为代理类的class信息已经存在于内存中,所以可以通过反射⽅式实例化。
这个应该怎么理解呢?
可以跟上⾯讲过的静态代理对⽐下,静态代理是需要开发⼈员⾃⼰实现代理类的逻辑的,且代理类的class信息是在程序运⾏之前就已经可以获取到的了,.java⽂件经过编译后可以得到.class⽂件;
⽽动态代理是不需要开发⼈员⾃⼰实现代理类的,也就是说使⽤动态代理⽅式的话,项⽬代码中是不存在代理类的.java⽂件的,既然代理类未由开发者实现,那么程序经过编译之后肯定也不会有代理类的.class⽂件,
也就是说经过编译之后程序未启动运⾏之前,关于代理类的信息我们⼀⽆所知,它是在程序运⾏过程中需要⽤到的时候才会由jvm动态⽣成的,⽽且⽣成之后也只存在于内存中,不会写到磁盘保存成.class⽂件,更加不会保存为.java⽂件;
在程序重启或者说发⽣了gc,这个代理类的class信息从内存中被卸载之后,关于这个代理类的信息就没有了,只有当代码再次访问到代理对象时,才⼜会重新⽣成代理类的class信息。
2)动态代理与静态代理的区别是什么?
上⾯已经讲述,不再赘述。
3)为什么需要引⼊动态代理?
这就不得不说到静态代理的弊端,我们引⼊新事物,必定是因为旧事物存在不合理之处,所以才引⼊新的事物来弥补它的缺陷。
那静态代理有什么缺陷呢?
我们知道静态代理是需要开发者⾃⼰实现代理类逻辑的,也就是说要对某个类进⾏代理的话,需要实现这个类相应的代理类;
如果⽬标类的数量很多的话,代理类的实现也必然得很多,可能会造成代码量过于庞⼤,可能会增加代码的冗余度...
再者,如果⽬标类需要代理的⽅法很多的话,代理类需要对这些⽅法⼀⼀实现代理逻辑,代理类的实现也将会很庞⼤。

本文发布于:2023-05-06 15:42:16,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/90/98142.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:代理   需要   标类
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图