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位数据,可变波…...
【Wiki】XWiki数据备份
XWiki为主题使用java开发的开源wiki,官网地址如下: https://www.xwiki.org/xwiki/bin/view/Main/ 目录1、 XWiki升级数据备份1.1、 获取XWiki配置的数据库与持久化目录信息1.2 备份数据库信息1.3 备份持久化目录2、XWiki数据迁移如果一个知识库不能确保数…...
ctk框架开发Qt插件应用示例工程
目录 前言 约定 插件工程pluginApp: 主启动工程StartApp: 效果演示 结语...
spring5源码篇(4)——beanFactoryPostProcessor执行/注解bean的装配
spring-framework 版本:v5.3.19 前面研究了beanDefinition的注册,但也仅仅是注册这一动作。那么在spring容器启动的过程中,是何时/如何装配的?以及装配的bean是如何注入的? (考虑到xml方式基本不用了以及篇…...
masstransit的message几个高级用法
1)问题,Class MessageA 基类,Class MessageB继承自MessageA; 用bus.Publish方法本想把有些消息只发给B队列,结果由于其继承关系A队列也获得了消息; 解决方法用send, Uri uri new Uri(RabbitM…...
漏洞分析丨cve-2012-0003
作者:黑蛋一、漏洞简介这次漏洞属于堆溢出漏洞,他是MIDI文件中存在的堆溢出漏洞。在IE6,IE7,IE8中都存在这个漏洞。而这个漏洞是Winmm.dll中产生的。二、漏洞环境虚拟机调试工具目标软件辅助工具XP-SP3、KaliOD、IDAIE6Windbg组件gflags.exe三…...
rm命令——删除文件或目录
rm命令是英文单词remove的缩写,主要功能是删除文件或目录。 因为删除文件是一个破坏性动作,因此,在使用时需要格外小心,在执行之前一定要再三确认删除的是哪个目录中的什么文件。 rm命令的语法格式如下: rm [选项] …...
【零基础入门学习Python---Python的基本语法使用】
一.Python基本语法使用 Python是一种易学且功能强大的编程语言,具有简洁的语法和广泛的应用领域。在本文中,我们将介绍Python的基本语法使用,以帮助初学者快速入门Python编程。 1.1 注释 Python 支持两种类型的注释:单行注释和多行注释。 单行注释:以 # 符号开头,从 # …...
数据仓库相关概念的解释
数据仓库相关概念的解释 文章目录数据仓库相关概念的解释1 ETL是什么?ETL体系结构2 数据流向何为数仓DW3 ODS 是什么?4 数据仓库层DWDWD 明细层DWD 轻度汇总层(MID或DWB,data warehouse basis)DWS 主题层(D…...
1/4车、1/2车、整车悬架模糊PID控制仿真合集
目录 前言 1. 1/4悬架系统 1.1数学模型 1.2仿真分析 2. 1/2悬架系统 2.1数学模型 2.2仿真模型 2.3仿真分析 3. 整车悬架系统 3.1数学模型 3.2仿真分析 4.总结 前言 前面几篇文章介绍了LQR、SkyHook、H2/H∞、PID控制,接下来会继续介绍滑模、反步法、M…...
Linux性能补丁升级,避免不必要的跨核Wake-Up
导读一个由英特尔发起的、旨在改进Linux内核公平调度程序代码的补丁系列,也看到了来自AMD工程师和其他利益相关者的测试/反馈,并继续进行改进。这个补丁系列的重点是避免在不必要的情况下发生过多的跨核唤醒(Cross-CPU Wake-up)。这样一来,这…...
眼查看网站开发语言/西安百度推广代运营
前言: 在网上找了很多有道云笔记的markdown笔记如何插入本地图片,试了好几种方式都是一时可以显示而已,只要电脑重启或者换终端查看就无法显示图片了。网上常用的方法无非两种有效:github、博客。接下来介绍第3种方法,…...
崇安区网站建设价格/自动引流免费app
对于新浪微博这块一直很纠结,auth认证让人吐血。之前项目用到的都是copy别人的,最近想详细了解下,就简单实现一二,以便以后自己更好的运用. 准别好以下常量 public String consumerKey "2803926882";// key public S…...
济南seo网站关键词优化排名/如何做百度关键词推广
求助各位大神,dell T630电脑进大白菜PE后识别不出来阵列,装驱动又不会装,现在进BIOS显示HARD raid PERC H330的阵列卡出感叹号了(device path:pciroot(0x0)PCI(0X1A,0X0)/USB(0X0,0X0)/USB(0X4,…...
注册做网站的营业执照/网页制作官方网站
Redis--事物 一、redis的事物 Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证:事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断…...
wordpress主题安装全解析/百度资源平台
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼我有一个57600行2列的矩阵,想用pdist函数求此矩阵任意两个行向量的距离,可是运行时出现了这样的错误:---------------------------------------------------------------------Segmentation viol…...
wordpress 首页导航/竞价推广是什么工作
u-boot版本: v2009.08 看到很多文章都把两者描述为u-boot的入口地址,概念有点模糊。 其实可以这么理解: _start是可以动态变化,而TEXT_BASE是链接时就确定的地址。 _start是实际运行的地址,而TEXT_BASE是要copy到sdram中运行的…...