动态代理深入挖掘
(笔记代码视频私我或者+ csheima7)
为什么要讲动态代理
- 框架底层几乎离不开反射加动态代理,可见其重要性;
- 我们大多数同学只是会用,不明白其核心原理,这就可能会导致你在使用的过程中出现问题而不明其所以然;
- 出去面试我们要不要说点有深度的东西呢?当然要!不然企业凭什么选择你不选择别人;
- 开启大家对于Java学习的新大门,领悟Java本身的乐趣,这才是长久在这个行业的生存之道。有一句话说的好:知之者不如好之者,好之者不如乐之者;
代理模式的优势
-
扫盲:什么是代理模式?
生活中的例子:房屋中介
房主:我只想把我房子卖掉(买卖双方交易),200万,你把钱给我,我把房子过户到你名下;
中介:推广、带客户看房、准备合同、买卖双方签署合同、买卖双方交易、售后;
这里中介就是房主的代理,房主只是想把自己的房子卖掉,不需要关心其它的事情;
中介可以代理很多房主的房子,他们提供房屋销售的全套流程:售前、交易、售后;
需要注意的是,其中的交易是需要被代理者来完成的;
这个例子中,代理对象就是中介对象,被代理对象就是房主对象,代理对象自己无法完成交易流程,所以代理对象中需要有一个被代理对象作为其成员实例,以用来完成被代理的核心业务逻辑(交易);
具体用代码描述
/** * Created By gao_e on 2020/3/16 10:22 * 卖房子的人 * 可以是房主,也可以是中介 */ public interface HouseSeller { // 卖房 void sellHouse(); }
/** * Created By gao_e on 2020/3/16 10:21 * 房主 */ public class MasterOfHouse implements HouseSeller { private Integer howMuchW; public MasterOfHouse(Integer howMuchW) { this.howMuchW = howMuchW; } @Override public void sellHouse() { System.out.println("一口价"+this.howMuchW+"万"); System.out.println("收钱"); System.out.println("过户"); } }
/** * Created By gao_e on 2020/3/16 10:27 * 房屋中介 */ public class HouseAgent implements HouseSeller { private HouseSeller houseSeller; public HouseAgent(HouseSeller houseSeller) { this.houseSeller = houseSeller; } @Override public void sellHouse() { this.doSomethingOnBefore(); this.houseSeller.sellHouse(); this.doSomethingOnAfter(); } private void doSomethingOnBefore() { System.out.println("售前..."); } private void doSomethingOnAfter() { System.out.println("售后..."); } }
/** * Created By gao_e on 2020/3/16 10:34 * 卖房、买房流程 */ public class SellHouse { public static void main(String[] args) { System.out.println("一个房主将卖房事情委托给中介,中介针对这个房子会单独创建出一个中介(代理)对象"); HouseSeller houseSeller = new HouseAgent(new MasterOfHouse(2000)); System.out.println("中介将房子挂出来卖,买家来买房"); houseSeller.sellHouse(); } }
结果如下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KH0BG241-1584588747921)(…\素材\image-20200316112735635.png)]
-
为什么要使用代理模式?
1、职责清晰,真实的角色就是实现实际的业务逻辑(房主卖房逻辑始终不用改动),不用关心其它非本职责的事务;
2、最终通过代理来完成真实角色的事务,并且可以对真实事务逻辑做增强操作,附带的结果就是编程简洁清晰;
3、实现对真实角色的保护,有的时候,代理增强逻辑中可以判断决定是否去执行其代理的真实对象的业务逻辑(举例:如果买房客户资金不够,那么也没有必要联系房东做房屋交易操作,这里起到了屏蔽作用);
4、低耦合高内聚(一个好的内聚模块应当恰好做一件事),拓展性强,可以实现用不同的代理类,做不一样的代理操作,方便更换具体增强逻辑;
先讲静态代理
什么是静态代理?
- 代理者与委托者是一对一的,十个不同的委托类就需要提供十个不同的代理类;
- 代理类需要我们自己编写, 代理类和委托类的关系在程序运行前就确定了;
- 上面举得房屋中介的例子就是用的静态代理;
代码结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xIeEqNHA-1584588747922)(…\素材\image-20200316145219181.png)]
-
代理接口;
public interface Subject { void doSomething(); }
-
委托类,真实业务处理者;
public class RealSubject implements Subject { @Override public void doSomething() { System.out.println("do real something"); } }
-
对应的代理类;
public class ProxySubject implements Subject { public ProxySubject(Subject realSubject) { this.realSubject = realSubject; } private Subject realSubject; @Override public void doSomething() { this.doOtherThing(); realSubject.doSomething(); this.doOtherThing(); } private void doOtherThing() { System.out.println("doOtherThing"); } }
-
再加一个静态代理类工厂(非必须);
public class SubjectStaticFactory { /** * 对客户类来说,其并不知道返回的是代理类对象还是委托类对象 */ public static Subject getInstance() { return new ProxySubject(new RealSubject()); } }
-
需要处理业务的客户端;
public class Client { public static void main(String[] args) { Subject subject = SubjectStaticFactory.getInstance(); subject.doSomething(); } }
结果——[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ver67oLg-1584588747922)(…\素材\image-20200316150625407.png)]
静态代理的缺点
- 代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了;
- 如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度;
什么是动态代理?
- 你想让它代理谁它就代理谁,它会给你生成一个代理对象(代理你指定的类),用其完成具体代理逻辑;
- 动态代理类的源码是在程序运行期间由JVM根据反射、 ASM生成java的字节码等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。 (ASM:一个小而快的字节码处理框架,用来转换字节码并生成新的类 )
动态代理的缺点
- 效率问题(毕竟需要根据委托类Class对象信息动态操作字节码生成代理类);
JDK动态代理原理探究
先回顾一下它是如何使用的
需要基于接口
1、调用代理逻辑的执行器InvocationHadler(它并不是实际上的代理类)
分为两种情况
-
有委托者(被