当前位置: 首页 > news >正文

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&#xff…...

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&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...