什么是代理模式
对一个对象提供一个代理对象,使用代理对象控制对原对象的引用。
使用代理模式目的
透明的控制对象的访问,代理模式的作用是隐藏对象的复杂性,控制对对象的访问,并在必要时增加一些额外的功能。
代理模式的分类
静态代理
在编译期间就已经确定了代理关系,也就是说代理类和被代理类的关系在程序运行之前就已经确定了。静态代理需要自己定义一个代理类,这个代理类需要实现和被代理类一样的接口,然后在代理类中调用被代理类的方法,并且可以在方法前后添加一些额外的逻辑。
动态代理
在运行期间动态生成代理类,也就是说代理类和被代理类的关系是在程序运行时动态生成的。
类是如何动态生成的
Java 虚拟机类加载过程主要分为五个阶段:加载、验证、准备、解析、初始化。
加载阶段中,关于获取二进制字节流,有以下几种方式:
1)从本地获取字节码:Java虚拟机可以从本地文件系统加载类的字节码文件。
2)从网络中获取二进制字节流:Java虚拟机也可以从网络中加载类的字节码数据。使用类加载器的getResourceAsStream()方法,通过指定URL的方式来获取InputStram,然后通过读取InputStream获取字节数据。
3)运行时就算生成:这种场景使用最多的是动态代理技术,在java.lang.reflect.Proxy类中,就是用了ProxyGenerator.generateproxyClass来为特定接口生成形式为“*$Proxy”的代理类的二进制字节流。
所以动态代理就是想办法,根据接口或目标对象,计算出代理类的字节码,然后加载到JVM中使用。
动态代理分类
1)JDK动态代理
2)CGLib动态代理
两种动态代理技术的区别
JDK动态代理和CGLib动态代理是Java语言中实现动态代理的两种方式。区别如下:
1)基于的技术不同:JDK动态代理是基于Java反射机制实现的,而CGLib动态代理则是使用字节码生成技术实现的。
2)被代理类的要求不同:JDK动态代理只能代理实现了接口的类,而CGLib动态代理可以代理没有实现接口的类。
3)代理性能不同:JDK动态代理生成的代理类性能相对较低,因为它是基于反射实现的;而CGLib动态代理生成的代理类性能相对较高,因为它基于字节码生成技术(ASM)实现的。
4)代理方式不同:JDK动态代理是基于接口实现的,因此代理类必须实现被代理接口;CGLib动态代理是基于集成实现的,因此代理类继承被代理类。
综上所述,JDK动态代理适合代理接口方法,而CGLib动态代理适合代理普通类方法。
静态代理、动态代理的区别
1)实现方式不同:静态代理在编译期就已经确定了代理对象的类型,代理类需要手动编写。动态代理是在运行时动态生成代理对象,代理类不需要手动编写,而是由框架自动生成。
2)适用范围不同:静态代理只适用于代理对象类型固定、接口较少的情况下。因为每增加一个被代理的接口,就需要编写一个新的代理类。动态代理则可以代理任意的接口,无需编写新的代理类,因此更加灵活。
3)性能表现不同:由于静态代理在编译期就已经确定代理对象的类型,因此在运行时执行效率较高。而动态代理在运行时需要进行额外的代理对象生成,方法调用转发等操作,因此会存在一定的性能损失。
总的来说,静态代理适用于代理对象类型固定、接口较少、性能要求较高的情况。而动态代理则适用于代理对象类型不固定、接口较多、灵活性要求较高的情况。
代理模式结构图
1)抽象主题(Subject): 定义了真实主题和代理主题的共同接口
2)真实主题(Real Subject):定义了代理所代表对象,是代理所要代理的对象
3)代理(Proxy): 提供了与真实主题相同的接口,同时还负责创建和删除真实主题对象,使得客户端不直接与真实主题进行交互
4)客户端(Client): 通过代理访问真实对象
代理模式优点
1)代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用
2)代理对象可以扩展目标对象的功能
3)代理模式将客户端与目标对象分离,在一定程度上降低了系统的耦合度
代理模式缺点
增加了系统的复杂度
使用场景
1)功能增强
当需要对一个对象的访问提供一些额外操作时,可以使用代理模式
2)远程代理
实际上,RPC框架也可以看作是一种远程代理模式,通过远程代理,将网络通信、数据遍解码等细节隐藏起来,客户端使用RPC服务的时候,就像使用本地函数一样,无需了解跟服务器交互的细节。
3)防火墙代理
当你将浏览器配置成使用代理功能时,防火墙就将你的浏览器的请求转给互联网;当互联网返回响应时,代理服务器再把它转给你的浏览器。
4)保护代理
控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。