Java三种代理模式:静态代理、动态代理和CGLIB代理
Java三种代理模式:静态代理、动态代理和CGLIB代理
代理模式
代理模式是23种设计模式种的一种。代理模式是一种结构型设计模式,它允许为其他对象提供一个替代品或占位符,以控制对这个对象的访问。代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。
代理模式的构成
适配器模式一般包含三种角色:
- 抽象主题角色(Subject):通过接口或抽象类声明真实角色实现的业务方法。
- 代理主题角色(Proxy):实现抽象角色,是真实角色的代理(访问层),通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
- 真实主题角色(RealSubject):实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
代理模式主要有三种形式,分别是静态代理、动态代理(也称JDK代理、接口代理)和CGLIB代理(在内存动态创建对象而不需要实现接口,也可属于动态代理得范畴)
静态代理
静态代理是定义父类或者接口,然后被代理对象(即目标对象)与代理对象一起实现相同的接口或者是继承相同父类。代理对象与目标对象实现相同的接口,然后通过调用相同的方法来调用目标对象的方法。
- 优点:可不修改目标对象的功能,通过代理对象对目标功能扩展。
- 缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,一旦接口增加方法,目标对象与代理对象都要维护。
public interface Animal {void eat();
}
public class Dog implements Animal {@Overridepublic void eat() {System.out.println("吃吃吃");}
}
public class DogProxy implements Animal {private Animal target; //通过接口聚合目标对象public DogProxy(Animal target) {this.target = target;}@Overridepublic void eat() {System.out.println("静态代理开始");target.eat();System.out.println("静态代理结束");}
}
public class Main {public static void main(String[] args) {//创建被代理对象Dog dog = new Dog();//创建代理对象, 同时将被代理对象传递给代理对象DogProxy dogProxy = new DogProxy(dog);//通过代理对象,调用到被代理对象的方法dogProxy.eat();}
}
动态代理
动态代理是在运行时动态生成代理类,不需要手动编写代理类。Java种的动态代理主要是使用java.lang.reflect.Proxy和java.lang.reflect.InvocationHandler接口实现。
优点:灵活性高、减少重复代码、统一处理逻辑、可以代理多个真实类。
缺点:基于反射机制,性能较低,且无法代理final类和方法。
动态代理最主要的就是Proxy.newProxyInstance方法,它是用于创建动态代理对象的静态方法。它接受三个参数:
ClassLoader:用于加载动态代理类的类加载器。
interfaces:要代理的接口数组。
InvocationHandler:实现了InvocationHandler接口的对象,用于处理代理对象的方法调用。
public interface Animal {void eat();
}
public class Dog implements Animal {@Overridepublic void eat() {System.out.println("吃吃吃");}
}
public class AnimalInvocationHandler implements InvocationHandler {private Object target;public AnimalInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("吃前加热");Object result = method.invoke(target, args);System.out.println("吃后清理");return result;}
}
public class AnimalProxy {public static Animal createProxy(Animal animal) {return (Animal) Proxy.newProxyInstance(animal.getClass().getClassLoader(),animal.getClass().getInterfaces(),new AnimalInvocationHandler(animal));}
}
public class Main {public static void main(String[] args) {Dog dog = new Dog();Animal dogProxy = AnimalProxy.createProxy(dog);dogProxy.eat();}
}
JDK 动态代理有一个最致命的问题是其只能代理实现了接口的类。
为了解决这个问题,我们可以用 CGLIB 动态代理机制来避免。
CGLIB代理
CGLIB代理也叫作子类代理,它使目标对象不需要实现接口,是在内存中构建一个子类对象从而实现对目标对象功能扩展,有的也将CGLIB代理归属到动态代理。
CGLIB是一个高性能的代码生成包,它可以在运行期扩展java类与实现java接口。被许多AOP的框架使用(如Spring AOP)。Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类。
- 优点:可以为没有实现接口的类提供代理;性能比动态代理更高
- 缺点:生成的代理类较大、不支持final方法和类、对于final类和方法的处理相对复杂。
public class Dog {public void eat() {System.out.println("吃吃吃");}
}
public class AnimalMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("吃前加热");Object result = methodProxy.invokeSuper(o, objects);System.out.println("吃后清理");return result;}
}
public class DogCglibProxy {public static Dog createProxy() {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(Dog.class);enhancer.setCallback(new AnimalMethodInterceptor());return (Dog) enhancer.create();}
}
public class Main {public static void main(String[] args) {Dog dogProxy = DogCglibProxy.createProxy();dogProxy.eat();}
}
CGLIB与java动态代理的区别
- 实现方式:
- Java动态代理:使用
java.lang.reflect.Proxy
和InvocationHandler
接口。Java动态代理只能为接口创建代理对象,它是基于接口的代理。通过Proxy.newProxyInstance()
方法可以动态地生成实现了指定接口的代理类。 - CGLIB:通过继承目标类的方式创建代理对象。CGLIB可以为类创建代理,而不仅仅是接口。它通过生成目标类的子类,在子类中增加代理逻辑来实现动态代理。
- Java动态代理:使用
- 代理对象类型:
- Java动态代理:只能代理实现了接口的类。它要求目标对象实现一个或多个接口,然后通过代理对象来实现这些接口。
- CGLIB:可以代理没有实现任何接口的类。它通过继承目标类来创建代理对象,因此目标类不需要实现任何接口。
- 性能:
- Java动态代理:由于生成的代理对象是基于接口的,因此在调用代理方法时,会通过接口的方法调用
InvocationHandler
的invoke
方法,再由invoke
方法调用实际的目标方法。这一层额外的调用可能会引入一些性能开销。 - CGLIB:生成的代理对象是目标类的子类,因此调用代理方法时,直接调用子类中的方法,避免了通过接口的中间层,可能会在一些情况下具有更好的性能。
- Java动态代理:由于生成的代理对象是基于接口的,因此在调用代理方法时,会通过接口的方法调用
- 构造方式:
- Java动态代理:通过
Proxy.newProxyInstance()
方法动态生成代理对象,需要提供一个实现InvocationHandler
接口的对象。 - CGLIB:通过CGLIB库动态生成代理对象,无需提供
InvocationHandler
。CGLIB通过继承目标类并重写其中的方法来实现代理逻辑。
- Java动态代理:通过
应用场景
代理模式可以在多种场景下使用,包括但不限于以下几个方面:
- 访问控制:代理模式可以用来控制对实际对象的访问权限。比如,只有特定用户或角色才能访问某些敏感数据。
- 远程访问:代理模式可以用来处理远程对象的访问。比如,通过代理对象来访问远程Web服务。
- 延迟加载:代理模式可以用来实现延迟加载。比如,通过代理对象来加载某些资源或数据,以避免在程序启动时就加载所有数据。
- 虚拟代理:当需要延迟加载或预加载大量数据时,可以使用虚拟代理来提高程序的性能和效率。
应用场景
代理模式可以在多种场景下使用,包括但不限于以下几个方面:
- 访问控制:代理模式可以用来控制对实际对象的访问权限。比如,只有特定用户或角色才能访问某些敏感数据。
- 远程访问:代理模式可以用来处理远程对象的访问。比如,通过代理对象来访问远程Web服务。
- 延迟加载:代理模式可以用来实现延迟加载。比如,通过代理对象来加载某些资源或数据,以避免在程序启动时就加载所有数据。
- 虚拟代理:当需要延迟加载或预加载大量数据时,可以使用虚拟代理来提高程序的性能和效率。
- 缓存代理:当需要对经常使用的数据进行缓存时,可以使用缓存代理来管理和优化数据的访问效率。
相关文章:
Java三种代理模式:静态代理、动态代理和CGLIB代理
Java三种代理模式:静态代理、动态代理和CGLIB代理 代理模式 代理模式是23种设计模式种的一种。代理模式是一种结构型设计模式,它允许为其他对象提供一个替代品或占位符,以控制对这个对象的访问。代理模式可以在不修改被代理对象的基础上&am…...
vivado实现分析与收敛技巧9-分析使用率统计数据
实现问题的常见原因之一是未考量显式和隐式物理约束。例如 , 管脚分配 (pinout) 在逻辑布局上变为显式物理约束。 slice( 分片 ) 逻辑在大部分器件中都是一致的。但如下专用资源表示的是隐式物理约束 , 因为这些资源仅在某些位置…...
7nm项目之顶层规划——01数据导入
1.创建workspace 创建workspace后,在其目录下产生。 CORTEXA53.json文件是将有默认配置的文件master.json、有library的.config.json文件、tunes下CORTEXA53.tunes.json文件合并 注:tunes下的CORTEXA53.tunes.json文件可以覆盖一些master.json的设置…...
一键式紧急报警柱系统
随着科技的不断发展,一键式紧急报警柱在我们的生活和工作中扮演着越来越重要的角色。在这篇文章中,我们将一起探究与一键式紧急报警柱有关的知识。 一键式紧急报警柱是一种常见的安全防护设备,能够在紧急情况下快速发出警报,保护…...
4-Docker命令之docker run
1.docker run介绍 docker run命令是用来创建新的容器并运行相关命令 2.docker run用法 docker run [参数] [root@centos79 ~]# docker run --helpUsage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]Create and run a new container from an imageAliases:docker conta…...
【模电】直流通路与交流通路
直流通路与交流通路 通常,在放大电路中,直流电源的作用和交流信号的作用总是共存的,即静态电流、电压和动态电流、电压总是共存的。但是由于电容、电感等电抗元件的存在,直流量所流经的通路与交流信号所流经的通路不完全相同。因此…...
SpringBoot JprotoBuf序列化与反序列化的实现
文章目录 前言一、protobuf与JprotoBufprotobuf介绍JprotoBuf介绍protobuf与JprotoBuf的区别二、JprotoBuf特点三、类型转换对照表四、ProtobufClass编写五、序列化与反序列化测试六、使用JprotoBuf时的注意事项七、JprotoBuf与protobuf序列化反序列化结果比较前言 在软件开发…...
互联网Java工程师面试题·Spring Boot篇·第一弹
目录 1、什么是 Spring Boot? 2、Spring Boot 有哪些优点? 3、什么是 JavaConfig? 4、如何重新加载 Spring Boot 上的更改,而无需重新启动服务器? 5、Spring Boot 中的监视器是什么? 6、如何在 Sprin…...
HostHunter虚拟主机发现
HostHunter虚拟主机发现 1.HostHunter2.安装3.参数解释4.实例1.HostHunter HostHunter 一种工具,用于有效发现和提取提供大量目标 IPv4 或 IPv6 地址的主机名。HostHunter 利用简单的 OSINT 和主动协调技术将 IP 目标与虚拟主机名进行映射。这对于发现组织的真正攻击面特别有…...
鸿蒙开发:UIAbility组件间交互探索实战【鸿蒙专栏-22】
UIAbility组件间交互(设备内) 在设备内,UIAbility(用户界面能力)是系统调度的最小单元,它们负责展示用户界面和执行相关的业务逻辑。设备内的不同功能模块之间的交互是应用程序开发中的重要部分。本文将探讨设备内UIAbility之间的交互方式,包括启动应用内的UIAbility、…...
VSCode Vue 开发环境配置
Vue是前端开发中的重要工具与框架,可以保住开发者高效构建用户界面。 Vue2官方文档:https://v2.cn.vuejs.org/ Vue3官方文档:https://cn.vuejs.org/ Vue的安装和引用 Vue2的官方安装指南:https://v2.cn.vuejs.org/v2/guide/ins…...
clickhouse从mysql同步数据到clickhouse的几种方式
背景 我们的业务数据一般来说都是放在Mysql中的,而我们要分析的数据一般都存放在clickhouse中,所以如何把数据从mysql同步到ck,就变成了一个必须的步骤,本文简单记录下几种同步的方式 mysql数据同步到clickhouse 方式一&#x…...
“滑动窗口”算法实例
1 问题 给定一个字符串“S”,找出其中不含有重复字符的最长子串的长度。例如:S‘ABCABCBB’,则不含重复字符的最长字串长度为3.。S‘ABCDFG’,则不含重复字符的最长字串长度为6。要求设计一个Python程序实现该功能? 2 方法 按照一…...
分布式搜索引擎elasticsearch(一)
5.1 初始elasticsearch elasticsearch是一款非常强大的开源搜索引擎,可以帮助我们从海量数据中快速找到需要的内容。 elasticsearch是elastic stack的核心,负责存储、搜索、分析数据。 5.1.1正向索引 5.1.2elasticsearch采用倒排索引: 文档(document):每条数据就是一个…...
PTA 7-236 验证哥德巴赫猜想
哥德巴赫猜想之一是指一个偶数(2除外)可以拆分为两个素数之和。请验证这个猜想。 因为同一个偶数可能可以拆分为不同的素数对之和,这里要求结果素数对彼此最接近。 输入格式: 首先输入一个正整数T,表示测试数据的组数࿰…...
微信小程序 纯css画仪表盘
刚看到设计稿的时候第一时间想到的就是用canvas来做这个仪表盘,虽然本人的画布用的不是很好但还可以写一写😀。话不多说直接上代码。最后有纯css方法 <!--wxml--> <canvas canvas-id"circle" class"circle" >// js dat…...
成为AI产品经理——模型稳定性评估(PSI)
一、PSI作用 稳定性是指模型性能的稳定程度。 上线前需要进行模型的稳定性评估,是否达到上线标准。 上线后需要进行模型的稳定性的观测,判断模型是否需要迭代。 稳定度指标(population stability index ,PSI)。通过PSI指标,我们可以获得不…...
操作系统——进程同步
目录 一、信号量相关函数 1. 创建信号量集 2. 获取信号量集 3. 等待、通知信号量集 4. 控制信号量集 二、简单进程同步 1. 创建信号量集 2. P操作 3. V操作 4. 删除信号量集 5. 测试: 三、生产者与消费者 1. 创建、删除共享内存及信号量集 2. 单一生产…...
如何能够对使用ShaderGraph开发的Shader使用SetTextureOffset和SetTextureScale方法
假设在ShaderGraph中的纹理的引用名称为"_BaseMap",同时对这个"_BaseMap"纹理使用了采样的节点"SampleTexture2D",然后该采样节点的uv接入的TilingAndOffset节点,此时的关键步骤是新建一个Vector4属性…...
力扣572:另一棵树的子树
力扣572:另一棵树的子树 给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。 二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所…...
Linux系统中进程间通信(Inter-Process Communication, IPC)
文章目录 进程间通信介绍进程间通信目的进程间通信发展 管道什么是管道 匿名管道用fork来共享管道原理站在文件描述符角度-深度理解管道站在内核角度-管道本质管道读写规则管道特点 命名管道创建一个命名管道匿名管道与命名管道的区别命名管道的打开规则 命名管道的删除用命名管…...
【React + Typescript】使用WebPack包管理、各种扩展插件组成的初始模板,开源协议:CC-BY-4.0
React Typescript Webpack 模板 模板展示项目结构使用的部分扩展包页面配置代码Layout 公共容器组件路由Jspackage.json 开源模板下载TIP 模板展示 项目结构 使用的部分扩展包 📂 System ├── 📂 Plugin │ ├── 📄 file-loader | 在处…...
python 制作3d立体隐藏图
生成文件的3d图,例子: 文字: 隐藏图: 使用建议: 1、建议不用中文,因为中文太复杂,生成立体图效果不好。 2、需要指定FONT_PATH,为一个ttf文件,…...
layui+ssm实现数据批量删除
layuissm实现数据的批量删除 //数据表格table.render({id: adminList,elem: #adminList,url: ctx "/admin/getAdminList", //数据接口cellMinWidth: 80,even: true,toolbar: #toolbarDemo,//头部工具栏limit: 10,//每页条数limits: [10, 20, 30, 40],defaultToolba…...
国产AI边缘计算盒子,双核心A55丨2.5Tops算力
边缘计算盒子 双核心A55丨2.5Tops算力 ● 2.5TopsINT8算力,支持INT8/INT4/FP16多精度混合量化。 ● 4路以上1080p30fps视频编解码,IVE模块独立提供图像基础算子加速。 ● 支持Caffe、ONNX/PyTorch深度学习框架,提供resnet50、yolov5等AI算…...
C++作业4
代码整理, 将学过的三种运算符重载,每个至少实现一个运算符的重载 代码: #include <iostream>using namespace std;class Stu {friend const Stu operator*(const Stu &L,const Stu &R);friend bool operator<(const Stu …...
计算机网络(二)| 物理层上 | 数据通信基础知识 调制 频率范围 信噪比
文章目录 1 物理层基本概念2.数据通信基础知识2.1 数据通信基本概念2.2 信道基本概念2.2.1 基带调制(编码)方式2.2.2 带通调制方式 2.3 信道的极限速率影响因素2.3.1 **频率范围**2.3.2 **信噪比** 内容笔记来源于谢希任老师《计算机网络》 物理层重点 …...
[STM32-1.点灯大师上线】
学习了江协科技的前4课,除了打开套件的第一秒是开心的,后面的时间都是在骂娘。因为51的基础已经几乎忘干净,c语言已经还给谭浩强,模电数电还有点底子,硬着头皮上吧。 本篇主要是讲述学习点灯的过程和疑惑解释。 1.工…...
Web测试自动化工具Selenium的使用
Web测试自动化工具Selenium的使用 Selenium是一个Web应用测试的自动化工具,它通过模拟点击实现对Web应用的功能测试。测试时,除了Selenium,还需要对应的浏览器驱动,如在Chrome实现自动点击,则需要chromedriver。 Sel…...
VUE2+THREE.JS 按照行动轨迹移动人物模型并相机视角跟随人物
按照行动轨迹移动人物模型并相机视角跟随人物 1. 初始化加载模型2. 开始移动模型3. 人物模型启动4. 暂停模型移动5. 重置模型位置6. 切换区域动画7. 摄像机追踪模型8. 移动模型位置9.动画执行 人物按照上一篇博客所设定的关键点位置,匀速移动 1. 初始化加载模型 //…...
给公司做网站风险/高级seo培训
一、复习 1.1、字符设备驱动编写 alloc_chrdev_region/register_chrdev_regioncdev_alloccdev_initcdev_addclass_createdevice_create 注意:错误处理,goto语句 卸载的时候:释放申请的资源,并删除注册的结构体 1.2、设备文件创…...
自媒体专用网站免费/金华关键词优化平台
3.对数字进行全排列 使用itertools.permutations from itertools import permutations data_list permutations([1,2,3,4],2)#对数字1,2,3,4,进行两两组合,等同于全排列 for data in data_list: print(data) 结果 (1, 2) (1, 3) (1, 4) (2, 1) (2, 3) (2,…...
广东网页空间网站平台/什么平台可以免费打广告
如果想跟我一起讨论的话,就快加入我的知识星球吧。星球里有一千多位同样爱好安全技术的小伙伴一起交流! 常用工具: Nmap使用详解Sqlmap使用详解Metasploit Framework(MSF)的使用MSF中kiwi模块的使用MSF中mimikatz模块的使用Msfvenonm生成后门木马...
手机网站怎么做微信登陆6/windows7优化大师官方下载
firefox扩展开发(四) : 更多的窗口控件2008-06-11 17:00标签盒子 标签盒子是啥?大家都见过,就是分页标签: 对应的代码: <?xml version"1.0"?><?xml-stylesheet href"chrome://global/skin/…...
wordpress登陆可见插件/整站优化外包服务
C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing)。 内存映射文件对于托管世界的开发人员来说似乎很陌生,但它…...
网站建设广州/万网域名注册
日前有万科柏悦湾小区业主向中山日报反映称,最近一段时间业主进出小区发现了件奇怪事:物管公司在博爱路一侧进出小区的唯一一条外部道路上安了道闸,大家很担心下一步进出小区会不会被收费。业主梁先生表示,部分业主对物管此行为感…...