23模式--代理模式
本篇主要聊一些23中模型中的代理模式:
看一下百度百科的解释:
代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式其实有点像是:合作方—经纪人—明星这样关系。
合作方如果想要找明星合作,首先要找到经纪人,具体的谈判合同的事情,先和经纪人进行协商,最后达成合作。
其实代理模式有很多不同的形式,主要有三种:静态代理,动态代理(JDK代理,接口代理),Cglib代理。
一般的组成有:
- 抽象角色:通过接口或抽象类生命真实角色实现的业务方法。
- 代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
- 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
静态代理
静态代理在使用时,需要定义接口或者抽象类,也就是被代理对象(明星)与代理对象(经纪人)需要实现相同的接口或者是继承相同的父类。
现在进行代码演示:
-
接口
public interface BusinessInfa { // 签约方法void signContract();} -
被代理类
public class Star implements BusinessInfa {@Overridepublic void signContract() {System.out.println("我是大明星,我同意这份合同了");} } -
代理人
public class Agent implements BusinessInfa{ // 代理谁Star star;public Agent(Star star) {this.star = star;}@Overridepublic void signContract() { // 先联系明星经纪人System.out.println("你好,你找我家明星合作,可以和我谈"); // 谈合同不是简单就可以签约的,肯定要涉及道各种拉扯,合同条款以及费用System.out.println("和经纪人一起疯狂的如果老太太菜市场砍价一般,深入几天各种约各种谈"); // 最后同意了合同this.star.signContract(); // 就算合约签了,具体后面合作中的事情System.out.println("具体合作后现场一些细节,比如我家大明星,剧本改下台词超过十个字了,记不住台词");} } -
客户端调用代理人
public class client {public static void main(String[] args) {// 需要找大明星的联系方式没有,去找大明星公开的经纪人联系System.out.println("我是合作方,需要联系大明星,没办法只能先联系经纪人");BusinessInfa businessInfa=new Agent(new Star());businessInfa.signContract();}}
然后看一下结果:

现在看一下静态代理的优缺点
- 优点: 在不修改目标的对象功能的前提下,通过代理对象对目标公共进行扩展,例子中不会对明星签约的行动进行修改,但是具体谈判细节,以及合作后的出现事故等投通过经纪人进行谈判,毕竟明星给了经纪人钱的。
- 缺点:代理对象需要与目标的对象实现一样的接口,所以会有很多代理类,一旦接口增量了方法,目标对象和代理对象都要维护。也就是比如合作定义的行为,如果增加了明星和经纪人都需要增加行为。
静态代理其实是最方便理解代理这个原理的,而其它无论如何变化,都不能离开这个原理。
动态代理:jdk代理
动态代理类,是位于Java.lang.reflect包下类别的Interface InvocationHandler。其实也是通过反射实现的,所以代理对象不需要实现接口,但是目标对象要实现接口,否则不能用动态代理。而这是利用JDK的API实现的动态代理是在内存中构建代理对象的。
动态代理也被称之为JDK代理,接口代理。
还是老规矩直接用代码演示:
-
被代理类接口
//商务接口 毕竟经纪人代理明星的业务,也是要统一一下什么业务能代理 public interface BusinessInfa { // 签约方法void signContract();void breakContract();} -
被代理类:
public class Agent {// 代理谁Object target;public Agent(Object target) {this.target = target;}// 动态创建不同的代理对象public Object getProxyObject(){Object object=Proxy.newProxyInstance(this.target.getClass().getClassLoader(),this.target.getClass().getInterfaces(),new myInvocationHandler());return object;}class myInvocationHandler implements InvocationHandler{@Override // proxy 在其上调用方法的代理实例 method被代理的方法 代理方法中的参数argspublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 对第一个参数好奇是什么System.out.println("======================================="); // System.out.println(proxy); 这样打印会报错 不过可以看出第一个参数应该是代理对象 一般的时候没有什么用System.out.println(proxy.getClass());System.out.println("=======================================");// 因为要运行的方法没有返回值,所以不接受数据,通过return返回了 同时这里也是可以根据反射判断不同的方法,然后加入不同的逻辑if(method.getName()=="signContract" || method.getName().equals("signContract")){System.out.println("你好,你找我家明星合作,可以和我谈");method.invoke(target,args);System.out.println("后期出现事情,你们必须改,因为我家明星最漂亮,哪怕是她的错你们会原谅的。");// 这里可以返回所代理的类要运行的方法,不过因为我没有返回值,所以直接返回空return null;}else if (method.getName()=="breakContract" || method.getName().equals("breakContract")){System.out.println("你好,你们的错误");method.invoke(target,args);System.out.println("可恶的合作方,不理你们了");// 这里可以返回所代理的类要运行的方法,不过因为我没有返回值,所以直接返回空return null;}return null;}} } -
调用类
public class client {public static void main(String[] args) {// 需要找大明星的联系方式没有,去找大明星公开的经纪人联系System.out.println("我是合作方,需要联系大明星,没办法只能先联系经纪人");Agent agent= new Agent(new Star());BusinessInfa businessInfa = (BusinessInfa) agent.getProxyObject();businessInfa.signContract();System.out.println("*********************************************");businessInfa.breakContract();} }然后看一下输出结果:

可以看下类关系图:

jdk代理的优缺点:
- 优点 :JDK原声动态代理时java原声支持的、不需要任何外部依赖。而且可以动态生成代理类,方不需要像静态代理哪里代理类因为接口变化而不停的调整。
- 缺点:但是它只能基于接口进行代理,也就是被代理的对象也需要有一个接口,不然无法使用jdk代理,同时因为它已经继承了proxy了,java不支持多继承。
动态代理:Cglib代理
无论静态代理还是上面提到的JDK动态代理都需要实现一个接口,但是有时候对象只是一个单独的对象,并没有实现任何的接口,这个时候就需要使用目标对象的子类来实现。而聊到的Cglib动态代理就算通过这种方式实现代理的。
Cglib代理也叫做子类代理,其是再内存中构建了一个子类对象,从而实现对目标对象功能的扩展。Cglib代理是可以再运行期扩展java类与实现java接口,所以其广泛被需要AOP框架使用,其中就包括spring,通过Cglib实现方法拦截。
因为是内存中动态构建子类,所以Cglib代理类不能为final。同样如果目标对象的方法如果为final或者static,代理也会不对其方法进行代理。
其实AOP中不一定会都选择使用Cglib代理,我们开发中同样是如此选择的:
- 目标对象需要实现接口,那就使用JDK代理。
- 目标对象不需要实现接口,那句使用Cglib代理。
Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类。
需要Jar包
这个有两种情况,
-
如果引入的是Cglib的jar包就需要四个包:
asm.jar asm-commons.jar asm-tree.jar Cglib-*.*.jar(自己选版本)
-
如果使用 cglib-nodep的jar,直接导入这一个就行,因为其打包了cglib所需要的依赖jar包
代码演示
-
被代理的对象,无需实现接口
public class Star {public void signContract() {System.out.println("我是大明星,我同意这份合同了");}public void breakContract() {System.out.println("台词超过三句了,编辑不修改剧本,合作方的错误,毁约了。。。。");} } -
使用Cglib代理的增强代理类
// 经纪人代理 需要实现Cglib代理中接口方法MethodInterceptor public class Agent implements MethodInterceptor {// 代理谁Object target;public Agent(Object target) {this.target = target;}// 动态创建不同的代理对象public Object getProxyObject(){ // 创建一个Cglib包下的工具栏Enhancer enhancer=new Enhancer(); // 设置父类enhancer.setSuperclass(target.getClass()); // 设置回调函数,这个回调本身是自己所以enhancer.setCallback((Callback) this); // 创建子类对象 也就是代理对象return enhancer.create();}@Override // 需要重写这个方法,代理类调用方法的时候会走个方法 // o 代表的this 就算代理增强的对象 Method 被代理对象执行的方法,也就是拦截的方法 objects 方法的参数 methodProxy 用于调用super(非拦截方法);可以根据需要调用多次public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {// 因为要运行的方法没有返回值,所以不接受数据,通过return返回了 同时这里也是可以根据反射判断不同的方法,然后加入不同的逻辑if(method.getName()=="signContract" || method.getName().equals("signContract")){System.out.println("你好,你找我家明星合作,可以和我谈");method.invoke(target,objects);System.out.println("后期出现事情,你们必须改,因为我家明星最漂亮,哪怕是她的错你们会原谅的。");// 这里可以返回所代理的类要运行的方法,不过因为我没有返回值,所以直接返回空return null;}else if (method.getName()=="breakContract" || method.getName().equals("breakContract")){System.out.println("你好,你们的错误");method.invoke(target,objects);System.out.println("可恶的合作方,不理你们了");// 这里可以返回所代理的类要运行的方法,不过因为我没有返回值,所以直接返回空return null;}return null;} } -
调用测试的类
public class client {public static void main(String[] args) {// 需要找大明星的联系方式没有,去找大明星公开的经纪人联系System.out.println("我是合作方,需要联系大明星,没办法只能先联系经纪人");Agent agent= new Agent(new Star());Star star = (Star) agent.getProxyObject();star.signContract();System.out.println("*********************************************");star.breakContract();} }

也没有问题,可以实现动态代理。
补充 其它代理
这个只是写了几个代理的名字,也不是全部。
- 防火墙代理: 内网通过代理穿透防火墙,对公网进行访问。
- 缓存代理: 如果获取网络资源有些从缓存中回去资源,如果没有了再从其它地方获取资源。
- 远程代理:远程代理通过网络和真正的远程对象沟通信息。常见的翻墙梯子就算这个逻辑。
- 同步代理: 主要使用在多线程编程中,完成多线程间同步工作
相关文章:
23模式--代理模式
本篇主要聊一些23中模型中的代理模式: 看一下百度百科的解释: 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目…...
【Linux】信号的产生、保存、捕捉处理 (四种信号产生、核心存储、用户态与内核态、信号集及其操作函数)
文章目录1、什么是信号?2、信号的产生2.1 通过键盘产生信号2.2 通过系统调用产生信号2.3 硬件异常产生的信号2.4 由软件条件产生的信号2.5 进程的核心转储3、信号的保存4、信号的捕捉4.1 用户态和内核态4.2 用户态到内核态的切换4.3 信号捕捉过程5、信号集操作函数以…...
redis经典五种数据类型及底层实现
目录一、Redis源代码的核心部分1.redis源码在哪里2.src源码包下面该如何看?二、我们平时说redis是字典数据库KV键值对到底是什么1.6大类型说明(粗分)2.6大类型说明3.上帝视角4.Redis定义了redisObject结构体4.1 C语言struct结构体语法简介4.2 字典、KV是什么4.3 red…...
三十而立却被裁,打工人要如何应对职场危机?
又到金三银四就业季,对于部分职场人来说,年龄成为了他们找工作的最大限制。 因为绝大部分企业招聘中层干部以下岗位的时候,都会要求年龄不超过35周岁,再加上每年千万毕业生涌入社会,竞争程度相当激烈,这就导…...
java面试-java基础
char 变量能不能存贮一个中文汉字?为什么? char 变量可以存贮一个汉字,因为 Java 中使用的默认编码是 Unicode ,一个 char 类型占 2 个字节(16 bit),一个汉字是2个字节,所以放一个中…...
Kafka 消息不丢失
Kafka 消息不丢失生产者丢失消费者丢失不丢失配置Kafka 保证消息不丢失:只对已提交的消息 (committed message) 做有限度的持久化保证 已提交的消息:当 n 个 Broker 成功接收到该消息并写入到日志文件后,就告诉生产者该消息已成功提交有限度…...
ASEMI高压MOS管10N65参数,10N65规格,10N65封装
编辑-Z ASEMI高压MOS管10N65参数: 型号:10N65 漏极-源极电压(VDS):650V 栅源电压(VGS):30V 漏极电流(ID):10A 功耗(PDÿ…...
LeetCode-416. 分割等和子集
目录题目分析回溯法动态规划动态规划(压缩)题目来源 416. 分割等和子集 题目分析 这道题目是要找是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 那么只要找到集合里能够出现 sum / 2 的子集总和,就算是可以分割成两个相同元素和子集了…...
2021年 第12届 蓝桥杯 Java B组 省赛真题详解及小结【第2场省赛 2021.05.09】
一、试题A:求余(本题总分:5 分) 得:5分 本题总分:5 分 【问题描述】 在 C/C/Java/Python 等语言中,使用 % 表示求余,请问 2021%20 的值是多少? 【答案提交】 这是一道结果…...
elasticSearch写入原理
elasticSearch写入原理 最近学习完了es相关的课程整理除了es的核心内容,学习这东西知其然知其所以然,自己按照自己的理解整理了es相关的面试题。先热个身,整理一下es的写入原理,有不对的地方请大家指正。 这些原理的东西我觉得还是…...
第十四届蓝桥杯模拟赛(第三期)Python
1 进制转换 问题描述 请找到一个大于 2022 的最小数,这个数转换成十六进制之后,所有的数位(不含前导 0)都为字母(A 到 F)。 请将这个数的十进制形式作为答案提交。 答案:2730 def ch…...
Pytorch模型参数的保存和加载
目录 一、前言 二、参数保存 三、参数的加载 四、保存和加载整个模型 五、总结 一、前言 在模型训练完成后,我们需要保存模型参数值用于后续的测试过程。由于保存整个模型将耗费大量的存储,故推荐的做法是只保存参数,使用时只需在建好模…...
面试热点题:回溯算法之组合 组合与组合总和 III
什么是回溯算法? 回溯算法也可以叫回溯搜索算法,回溯是递归的"副产品",回溯的本质是穷举,然后选出我们需要的数据,回溯本身不是特别高效的算法,但我们可以通过"剪枝"来优化它。 理解回溯算法 回溯…...
java面试-jvm
JVM JVM 是 java 虚拟机,简单来说就是能执行标准 java 字节码的虚拟计算机 JVM 是如何工作的 首先程序在执行之前先要把 Java 代码(.java)转换成字节码(.class),JVM 通过类加载器(ClassLoade…...
vscode下载与使用
1.vscode下载 官网下载地址:Download Visual Studio Code - Mac, Linux, Windows下载太慢,推荐文章:解决VsCode下载慢问题_vscode下载太慢_迷小圈的博客-CSDN博客下载太慢,推荐下载链接:https://vscode.cdn.azure.cn/s…...
人员摔倒识别预警算法 opencv
人员摔倒识别预警算法通过opencv网络模型技术,人员摔倒识别预警算法能够智能检测现场画面中人员有没有摔倒,无需人为干预可以立刻抓拍告警。OpenCV的全称是Open Source Computer Vision Library,是一个跨平台的计算机视觉处理开源软件库&…...
华为OD机试题 - 火星文计算(JavaScript)| 机考必刷
更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:火星文计算题目输入输出示例一输入输出说明Code解题思路版权说明…...
AI人工智能 - 初探
1.应用场景 主要用于了解和系统学习AI,从而可以在工作生活中利用AI做一些事。 2.学习/操作 1.文档阅读 下面的内容来自于与chatGPT的对话 2.整理输出 介绍AI 人工智能(Artificial Intelligence,简称AI)是计算机科学中的一个分支&…...
Spring-AOP工作流程
Spring-AOP工作流程 3,AOP工作流程 3.1 AOP工作流程 由于AOP是基于Spring容器管理的bean做的增强,所以整个工作过程需要从Spring加载bean说起: 流程1:Spring容器启动 容器启动就需要去加载bean,哪些类需要被加载呢?需要被增强的类,如:B…...
C51---串口发送指令,控制LED灯亮灭
1.Code: #include "reg52.h" #include "intrins.h" sfr AUXR 0x8E; sbit D5 P3^7; void UartInit(void) //9600bps11.0592MHz { //PCON & 0x7F; //波特率不倍速 AUXR 0x01; SCON 0x50; //8位数据,可变波…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
