Java 代理模式之静态代理与动态代理
1,代理模式
代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。
代理模式的目的:
(1)通过引入代理对象的方式来间接访问目标对象,防止直接访问目标对象给系统带来的不必要复杂性;
(2)通过代理对象对访问进行控制;
代理模式一般会有三个角色:
抽象角色:指代理角色和真实角色对外提供的公共方法,一般为一个接口。
真实角色:需要实现抽象角色接口,定义了真实角色所要实现的业务逻辑,以便供代理角色调用。也就是真正的业务逻辑在此。
代理角色:需要实现抽象角色接口,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。将统一的流程控制都放到代理角色中处理。
2,静态代理
静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类。一般来说,被代理对象和代理对象是一对一的关系,当然一个代理对象对应多个被代理对象也是可以的。
比如我要卖房子,但是我不会自己去卖,我会先找到中介,让中介去卖。
这里的抽象角色就是卖房子。
真实角色就是我卖房子。
代理角色就是中介卖房子。
新建一个抽象接口:
public interface SailRoom {//卖房子void sailRoom();
}
创建真实的卖房子的对象:
public class Me implements SailRoom{@Overridepublic void sailRoom() {System.out.println("sail my room");}
}
创建一个中介代理类:
public class RoomProxy implements SailRoom {private Me me;public RoomProxy(Me me) {this.me = me;}private void before(){System.out.println("before sail room");}private void after(){System.out.println("after sail room");}@Overridepublic void sailRoom() {before();me.sailRoom();after();}
}
在应用时这么使用:
RoomProxy proxy =new RoomProxy(new Me());
proxy.sailRoom();
那我如果要想再卖一个二手苹果手机,那我找中介就不行了,那我只能再去创建一个新的卖二手手机代理,去去卖二手手机。
创建一个新的卖手机的接口:
public interface SailPhone {/** 卖手机* */void sailPhone();
}
实现这个接口:
public class Me implements SailRoom,SailPhone{@Overridepublic void sailRoom() {System.out.println("sail my room");}@Overridepublic void sailPhone() {System.out.println("sail my phone");}
}
创建一个卖手机的代理类:
public class PhoneProxy implements SailPhone{private Me me;private void before(){System.out.println("before sail phone");}private void after(){System.out.println("after sail phone");}@Overridepublic void sailPhone() {before();me.sailPhone();after();}
}
使用时:
public static void main(String[] args) {Me me =new Me();RoomProxy proxy =new RoomProxy(me);PhoneProxy phoneProxy =new PhoneProxy(me);proxy.sailRoom();phoneProxy.sailPhone();
}
输出:
before sail room
sail my room
after sail room
before sail phone
sail my phone
after sail phone
从上面可以很明显的看出静态代理模式的缺点:
1,如果有多个类需要代理,那么就需要创建多个代理类分别代理目标对象,工作量较大,不利于维护。
2,当接口的方法增加或修改的时候,很多类都需要修改。因为,目标类和代理类都实现了相同的接口
3,动态代理
上面那个案例,用动态代理怎么实现呢?
下面我们用jdk的动态代理来实现:
先创建我们的动态代理类:
public class SailProxy implements InvocationHandler {private Object object;public SailProxy(Object object) {this.object = object;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("do before");Object invoke = method.invoke(object, args);System.out.println("do after");return invoke;}
}
在使用时:
public class Test {public static void main(String[] args) {Me me =new Me();SailProxy sailProxy =new SailProxy(me);Object o =Proxy.newProxyInstance(me.getClass().getClassLoader(), new Class[]{SailRoom.class,SailPhone.class}, sailProxy);SailRoom sailRoom = (SailRoom) o;sailRoom.sailRoom();SailPhone sailPhone = (SailPhone) o;sailPhone.sailPhone();}
}
输出:
do before
sail my room
do after
do before
sail my phone
do after
这样我们就实现了一劳永逸,只创建一个代理类,就可以代理无数个接口。没错,是接口,JDK的实现的动态代理,它代理的只是接口。
下面我们就来详细讲解一下上个案例。
首先,在SailProxy中,我们实现了InvocationHandler这个接口,实现了接口的invoke方法。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("do before");Object invoke = method.invoke(object, args);System.out.println("do after");return invoke;
}
其中 参数一Object proxy 与:
Object o =Proxy.newProxyInstance(me.getClass().getClassLoader(), new Class[]{SailRoom.class,SailPhone.class}, sailProxy);
的返回值Object o是一个对象,都是代表的传入的 new Class[]{SailRoom.class,SailPhone.class}
的接口对象。可以强转为SailRoom也可以强转为SailPhone。
接下来看第二个参数Method method,它代表的是你调用的接口的方法,可以是sailRoom(),也可以是sailPhone()。
第三个参数Object[] args就是接口方法的参数。
当你调用sailRoom.sailRoom()时,就会回调到invoke方法里面,调用
此时的method就是sailRoom(),object就是Me这个实际的角色,args就是方法参数,此处为空。
注意:
1,jdk实现的动态代理只能代理接口,不能代理类。
2,动态代理生成的代理类并不像普通类那样通过Javac生成class文件存放在磁盘中,他并不是一个真正的class文件,它只是存放在内存中。
相关文章:
Java 代理模式之静态代理与动态代理
1,代理模式 代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。 代理模式的目的: (1)通过引入代理对象的方式来间接访问目标对象,防…...
打造基于终端命令行的IDE,Termux配置Vim C++开发环境
Termux配置Vim C开发环境,打造基于终端命令行的IDE 主要利用VimCoc插件,配置C的代码提示等功能。 Termux换源 打开termux,输入termux-change-repo 找到mirrors.tuna.tsinghua.edu.cn,清华源,空格选中,回…...
【初阶C语言】操作符2---表达式求值
前言:本节重点介绍操作符的使用,如,优先级高低、类型转换等 一、逻辑操作符 前言:逻辑操作符包括逻辑与(&&)和逻辑或(||),操作对象:两个 1.逻辑与&…...
代码随想录day50|123. 买卖股票的最佳时机 III188. 买卖股票的最佳时机 IV
123. 买卖股票的最佳时机 III class Solution:def maxProfit(self, prices: List[int]) -> int:dp[[0]*5 for _ in range(len(prices))]dp[0][0]0dp[0][1]-prices[0]dp[0][2]0dp[0][3]-prices[0]dp[0][4]0for i in range(1,len(prices)):dp[i][0] dp[i-1][0]dp[i][1] max…...
Word 表格单元格无法垂直居中
Word使用 由于平时也需要用到word编写一些文档,但是咱们就是用的少,很多操作或者技巧不太清楚,很多小问题处理起来反而需要消耗很多时间,所以在这里记录平时遇到的一些问题。 表格无法垂直居中 类似于上图的情况,总之…...
python实现Flask POST Demo
数据处理逻辑 from flask import Flask, requestapp Flask(__name__)app.route(/, methods[POST]) def index():username request.form[username]password request.form[password]if username "Jhon" and password "1":return f"<html>&l…...
3-Pytorch张量的运算、形状改变、自动微分
3-Pytorch张量的运算、形状改变、自动微分 1 导入必备库2 张量的运算3 张量的算数运算4 一个元素的张量可以使用tensor.item()方法转成标量5 torch.from_numpy()和tensor.numpy()6 张量的变形7 张量的自动微分8 使用with torch.no_grad():包含上下文中使其不再跟踪计算9 使用te…...
用户权限数据转换为用户组列表(3/3) - Excel PY公式
最近Excel圈里的大事情就是微软把PY塞进了Excel单元格,可以作为公式使用,轻松用PY做数据分析。系好安全带,老司机带你玩一把。 实例需求:如下是AD用户的列表,每个用户拥有该应用程序的只读或读写权限,现在需要创建新的…...
VS2022+CMAKE+OPENCV+QT+PCL安装及环境搭建
VS2022安装: Visual Studio 2022安装教程(千字图文详解),手把手带你安装运行VS2022以及背景图设置_vs安装教程_我不是大叔丶的博客-CSDN博客 CMAKE配置: win11下配置vscodecmake_心儿痒痒的博客-CSDN博客 OPENCV配…...
JavaScript的内置类
一、认识包装类型 1.原始类型的包装类 JavaScript的原始类型并非对象类型,所以从理论上来说,它们是没有办法获取属性或者调用方法的。 但是,在开发中会看到,我们会经常这样操作: var message "hello world&q…...
6.英语的十六种时态(三面旗):主动、被动、肯定、否定、一般疑问句、特殊疑问句。
目录 一、do句型(以动词allow举例)。 (1)主动语态表格。 (2)被动语态表格。 (3)否定。 二、be句型(表格里的时态可以参考,查不到对应的资料)…...
SpringBoot连接Redis与Redisson【代码】
系列文章目录 一、SpringBoot连接MySQL数据库实例【tk.mybatis连接mysql数据库】 二、SpringBoot连接Redis与Redisson【代码】 三、SpringBoot整合WebSocket【代码】 四、SpringBoot整合ElasticEearch【代码示例】 文章目录 系列文章目录代码下载地地址一、引入依赖二、修改配…...
ardupilot开发 --- MAVSDK 篇
概述 MAVSDK是各种编程语言的库集合,用于与MAVLink系统(如无人机、相机或地面系统)接口。这些库提供了一个简单的API,用于管理一个或多个车辆,提供对车辆信息和遥测的程序访问,以及对任务、移动和其他操作…...
腾讯云AI超级底座新升级:训练效率提升幅度达到3倍
大模型推动AI进入新纪元,对计算、存储、网络、数据检索及调度容错等方面提出了更高要求。在9月7日举行的2023腾讯全球数字生态大会“AI超级底座专场”上,腾讯云介绍异构计算全新产品矩阵“AI超级底座”及其新能力。 腾讯云副总裁王亚晨在开场致辞中表示&…...
AB测试结果分析
一、假设检验 根据样本(小流量)的观测结果,拒绝或接受关于总体(全部流量)的某个假设,称为假设检验。 假设检验的基本依据是小概率事件原理(小概率事件几乎不发生),如果…...
Python模块和包:sys模块、os模块和变量函数的使用
文章目录 模块(module)引入外部模块引入部分内容包 (package)示例代码开箱即用sys模块sys.argvsys.modulessys.pathsys.platformsys.exit() os模块os.environos.system()os模块中的变量、函数和类 测试代码模块中的变量和函数的使用 总结:pyt…...
计算机软件工程毕业设计题目推荐
文章目录 0 简介1 如何选题2 最新软件工程毕设选题3 最后 0 简介 学长搜集分享最新的软件工程业专业毕设选题,难度适中,适合作为毕业设计,大家参考。 学长整理的题目标准: 相对容易工作量达标题目新颖 1 如何选题 最近非常多的…...
嵌入式学习笔记(25)串口通信的基本原理
三根通信线:Tx Rx GND (1)任何通信都要有信息作为传输载体,或者有线的或则无线的。 (2)串口通信时有线通信,是通过串口线来通信的。 (3)串口通信最少需要2根ÿ…...
c++学习第十三
1)循环引用的案例及解决办法: #include <iostream> #include <memory> using namespace std; class A;class B { public:B(){cout<<"B constructor---"<<endl;}~B(){cout<<"B deconstructor----"<<endl;}std::weak_…...
java复习-线程的同步和死锁
线程的同步和死锁 同步问题引出 当多个线程访问同一资源时,会出现不同步问题。比如当票贩子A(线程A)已经通过了“判断”,但由于网络延迟,暂未修改票数的间隔时间内,票贩子B(线程B)…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
