首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

动态代理,JavaSE最难懂的知识点

今天是刘小爱自学Java的第54天。

感谢你的观看,谢谢你。

话不多说,开始今天的学习:

终于还是要学动态代理了,不管多难最终还是得搞定它。

在学它之前,先学习一种设计模式。

一、装饰设计模式

举一个现实里明星和经纪人的例子:

现有一个明星,emm,就叫洛天依吧。

明星是一种身份,很多人都可以是明星,在Java里面可以将其定义成一个接口。

洛天依具体是指某个人,在Java里面可以将其定义成一个类,同时她的身份就是明星,那么实现明星接口就好了。

1LuoTianYi类

创建star接口

这是一个明星接口,有三个抽象方法:

唱歌sing(int money)方法,money就是出场费;

跳舞dance(int money)方法,也需要对应的出场费;

休息Sleep()方法。

不同的明星会有不同的歌和舞,所以使用抽象方法表示。

创建LuoTianYi类

她是一个明星,所以需要实现star接口,并重写其中的方法,说明自己会唱什么歌,会跳什么舞。

好,现在问题来了,有人要请洛天依唱歌跳舞。

我们都知道明星一般都会有自己的经纪人,一般都是由经纪人出面谈合作。

噔噔蹬蹬,刘小爱闪亮登场了,刘小爱是谁?

他是LuoTianYi的经纪人。

2刘小爱类

创建刘小爱类

类中有一个成员变量Star,构造方法参数为star。

这是什么意思呢?

刘小爱同时是很多明星的经纪人,所以他的参数为star接口,创建该类对象的时候,需要传入star接口的实现类。

找那个明星合作,创建刘小爱对象时说明就好了,这是面向接口编程的核心思想。

重写Sing()方法

现在有人要谈唱歌合作,那由刘小爱去谈价格,价格不够那不行,价格够了就让对应的明星出场唱歌。

重写Dance()方法

同样的道理,也是价格谈判,出场费都是1万。

重写sleep()方法

休息时间,不谈合作。

3测试类

最后一切都设置好了,做一个测试:

创建刘小爱对象

同时说明此时要找哪位明星谈合作,哦,是LuoTianYi。

说明合作价格

唱歌一万五,跳舞五千。

控制台输出

唱歌钱够了,所以LuoTianYi开始唱歌了;

跳舞钱不够,所以没有跳舞。

刘小爱这个类就是LuoTianYi这个类的代理。

调用者找洛天依合作,其实是在和刘小爱在谈,在调用者的眼里,刘小爱就是LuoTianYi。

现在合作谈拢了,由谁去执行?由LuoTianYi去执行。

在IO流中,也有和其相似的情况:

我们使用的是缓冲字符流,但是缓冲流的底层是由字符流来执行的,那么缓冲字符流就是字符流的代理。

它们都对应Java中的一种设计模式,叫装饰设计模式:

装饰者:缓冲字符流、刘小爱就是装饰者

被装饰者:字符流、洛天依就是被装饰者

装饰者将被装饰者的方法增强了

该设计模式其实和Java中的继承很相似:

父类就相当于被装饰者

子类就相当于装饰者

子类重写方法就是在增强父类的方法

只不过该设计模式在代码层面比继承更具有拓展性。

学习了装饰设计模式,接着开始动态代理的学习。

二、动态代理

装饰设计模式和动态代理很相似,它是一种静态代理。

如何理解静态和动态?

静态:代理类是创建了的,比如例子中的刘小爱

动态:代理类是不用创建的

在Java里有一个类叫Proxy,翻译过来就是代理的意思。

用这个类可以动态构建一个代理类对象:

使用newProxyInstance()方法,该方法是一个静态方法,所以用类名直接可以调用。

将该方法拆分记忆:new 创建;Proxy 代理;Instance 实例化;也就是创建代理对象,很好记。

现在我们来仔细分析该方法的三个参数,看源码:

ClassLoader loader

ClassLoader,类加载器,昨天就接触过。

我们写的类,本质上是.java文件,同时开发工具会自动编译成.class文件,但它们都是存放在硬盘上的。

而类加载器就是将类加载进内存,这样才能够运行。

Class[] interfaces

interfaces,接口的意思。我个人学Java的一个习惯是先理解这个英文单词是什么意思再去记忆其作用。

并且很多命名规则都是见名知意的。

这个参数就是接口对应的Class对象,什么接口?就是被代理类实现的接口,因为它可以实现很多个接口,所以是一个数组。

InvocationHandler h

InvocationHandle,翻译过来就是调用处理器。

它是一个接口,我们继续看它的源码:

该接口只有一个方法invoke:

proxy:这个就是代理对象

method:这个也就是代理对象调用的方法(例子中的sing方法、dance方法、sleep方法)

args:这个是方法中的参数

好,以上就是对newProxyInstance()方法的说明,完全弄懂了这个方法,也就弄懂了动态代理。

我们现在将代码补全:

被代理类的类加载器

被代理类是谁?例子中就是LuoTianYi,首先要获取它对应的Class对象。

ty.getClass():三种获取Class对象之一,ly是LuoTianYi的对象,利用对象ly的getClass方法。

拿到其对应的Class对象后,可以调用getClassLoader()方法获取对应的类加载器。

Java里面的很多方法看名字就能知道它的作用是什么。

所以ty.getClass().getClassLoader()就是获取被代理类LuoTianYi的类加载器.

被代理类所实现的接口

同样的道理,见名知意:

ty.getClass().getInterface()就是获取被代理类实现的接口对应的Class对象,例子中就是star这个接口。

调用处理器

这是一个接口,所以使用匿名内部类创建其实现类对象,同时重写接口中的invoke方法。

这块代码的编写,其实也就是例子中刘小爱这个类对star接口中的三个抽象方法的重写。

这是具体的业务逻辑,根据不同的需求编写不同的代码,其它的代码都是基本不变的。

其中method这个参数:

proxy调用sing方法时,method就是sing方法

proxy调用dance方法时,method就是dance方法

根据这个我们可以在其中填上方法的具体业务逻辑

代理类对象 proxy

代理类LiuXiaoAi我们是没有创建的,所以用的是它的父接口star来接受代理类对象,这是多态。

总结:

谢谢你的观看。

如果可以的话,麻烦帮忙点个赞,谢谢你。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200607A0IOHJ00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券