Java代理模式——静态代理与动态代理
代理模式
代理模式允许你为其他对象提供一个代理,以控制对这个对象的访问。代理模式在不改变实际对象的情况下,可以在访问对象时添加额外的功能。
可以理解为代理模式为被代理对象创造了一个替身,调用者可以通过这个替身去实现这个被代理对象的功能,这个替身也可以为被代理对象增加功能
静态代理
定义
使用时候需要定义接口或者父类。 代理类和委托类有共同的父类或父接口。
案例
首先定义一个接口 ITeacherDao,并在这个接口中定义一个teacher()方法。
package Static;public interface ITeacherDao {void teacher();
}
再写一个他的实现类,实现teacher()方法
package Static;public class TeacherDao implements ITeacherDao{@Overridepublic void teacher() {System.out.println("老师在教课");}
}
如上,我们实现了一个简单接口与他的实现类,接下来我们实现一个老师的静态代理类
package Static;public class TeacherDaoProxy implements ITeacherDao{private TeacherDao teacherDao;public TeacherDaoProxy(TeacherDao teacherDao){this.teacherDao = teacherDao;}@Overridepublic void teacher() {System.out.println("代理前");teacherDao.teacher();System.out.println("代理后");}
}
在这段代码中,我们实现了TeacherDao的代理类,并通过调用teacherDao这个对象使用了被代理对象的方法;我们在使用被代理对象方法前后都拓展了新的功能,这就是静态代理。
下面是主函数对于静态代理的使用
public class Main {public static void main(String[] args) {Static.TeacherDao teacherDao = new TeacherDao();TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);teacherDaoProxy.teacher();}
}
这说明我们的代理类在实现被代理对象的功能时也拓展了新的功能
但是,这样的模式也存在一种缺陷,就是我们的代理对象和被调用对象都要实现同一接口或父类,可能会出现多个代理类,接口如果要增加方法的话会有很多代理类需要维护;针对这一问题,Java的开发者定义了相关方法去解决,这就是我们下面要介绍的被代理类。
动态代理
定义
不需要实现接口,但是被代理的目标对象需要实现,调用jdk的api形成代理对象,
动态代理就是通过使用反射,动态地获取抽象接口的类型,从而获取相关特性进行代理。
案例
我们还是先定义一个接口
public interface ITeacherDao {void teacher();void sayhello();
}
接着我们定义他的实现类
public class TeacherDao implements ITeacherDao {@Overridepublic void teacher() {System.out.println("老师在教课");}@Overridepublic void sayhello() {System.out.println("hello");}
}
接着我们实现一个动态的代理类,可以动态代理原对象;在这个代理类中,我们使用到了Proxy.newProxyInstance 这个函数,他有三个参数,以下是三个参数的解释
1.target.getClass().getClassLoader()
:获取被代理对象的类加载器。这是用于加载代理类的类加载器。
2.target.getClass().getInterfaces()
:获取被代理对象实现的接口。这些接口是代理类将要实现的接口。
3.new InvocationHandler() { ... }
:创建一个匿名的 InvocationHandler 对象,它实现了invoke
方法,这是代理逻辑的核心部分。
我们在InvocationHandler() { ... }中调用了被代理对象的方法,并且做了一些扩展
public class FactoryProxy {private Object target;public FactoryProxy(Object target){this.target = target;}public Object getProxyIstance() {return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("代理前");Object returnVal = method.invoke(target,args);System.out.println("代理后");return returnVal;}});};
}
在主函数中调用被代理类,创建一个接口类,讲接口类传入被代理类,然后就可以定义接口类中的方法了,即实现了动态代理。
public class Main {public static void main(String[] args) {ITeacherDao iteacherDao = new TeacherDao();ITeacherDao proxyInstance = (ITeacherDao) new FactoryProxy(iteacherDao).getProxyIstance();proxyInstance.teacher();proxyInstance.sayhello();}
}
最终输出结果
可以看出,我们通过动态代理类实现了对目标对象的功能拓展
链接
java静态代理与动态代理: java静态代理与动态代理
相关文章:

Java代理模式——静态代理与动态代理
代理模式 代理模式允许你为其他对象提供一个代理,以控制对这个对象的访问。代理模式在不改变实际对象的情况下,可以在访问对象时添加额外的功能。 可以理解为代理模式为被代理对象创造了一个替身,调用者可以通过这个替身去实现这个被代理对…...
Vue day02 Computed和Watch
1.事件绑定 可以用 v-on 指令监听DOM 事件,并在触发时运行一些 JavaScript 代码。v-on 还可以接收一个需要调用的方法名称。 <button v-on:click"handler">good</button> methods: { handler: function (event) { if (event) { alert(event.t…...

【Java】一只小菜坤的编程题之旅【3】
文章目录 1丶判定是否互为字符重排2、杨辉三角3丶某公司的1个面试题(字符串包含问题) 1丶判定是否互为字符重排 这个题我们用一个非常简单的思想就能实现,我们先将字符串转换为字符数组,然后对字符数组进行排序,然后再…...
全面掌握 Jaeger 分布式调用链路跟踪理论和实战,Go 为所有使用 go-resty 库发起 HTTP 请求集成链路跟踪 jaeger(附源码)
全面掌握 Jaeger 分布式调用链路跟踪理论和实战,Go 为所有使用 go-resty 库发起 HTTP 请求集成链路跟踪 jaeger(附源码)。 介绍一个开源的分布式跟踪系统 Jaeger,首先从理论基础知识开始学习,将学习如何在 HTTP 请求中集成链路跟踪,以及如何在 GORM 框架实现,最后学习 …...
vue键盘和鼠标事件
1、键盘事件 **按Enter键** keyup.enter**按PageDown键** keyup.page-down **按Tab键** keyup.tab **按Delete键** keyup.delete **按ESC键** keyup.esc**按Space键** keyup.space **按↑(Up)键** keyup.up**按↓(Down)键** keyup…...
Chrome 手动代理设置 HTTP/Socks5
1、安装代理插件:SwitchyOmega 在线安装 从 Chrome 应用商店 安装,如果您无法从该链接安装,请使用下面的离线安装。 离线安装 ①、去 Github 下载 最新版安装包 ,或者直接 本地下载 文件进行安装。 ②、下载安装文件后…...

SpringBoot第35讲:SpringBoot集成连接池 - 默认连接池HikariCP
SpringBoot第35讲:SpringBoot集成连接池 - 默认连接池HikariCP 本文是SpringBoot第35讲,主要介绍数据库连接池,以及SpringBoot集成默认的HikariCP的实践。 文章目录 SpringBoot第35讲:SpringBoot集成连接池 - 默认连接池HikariCP1…...

选择最适合自己的笔记本
选择最适合自己的笔记本电脑 一、了解笔记本品牌一线品牌准一线品牌二线品牌三线品牌 二、笔记本入手渠道笔记本入手渠道 三、根据需求选择机型使用需求1.日常使用2.商务办公、财务3.轻度剪辑、ps4.代码5.创意设计6.游戏 四、笔记本电脑配置如何选1.cpu2.显卡(GPU&a…...
前端安全:探秘安全 HTTP 头的设置
在当今数字化时代,前端安全至关重要。除了应对常见的攻击方式外,通过设置安全 HTTP 头,我们可以加强网站的安全性,减少潜在的威胁。本文将为您详细解释什么是安全 HTTP 头,以及如何通过设置它们来保护您的前端应用。 1…...

python爬虫——爬虫伪装和反“反爬”
前言 爬虫伪装和反“反爬”是在爬虫领域中非常重要的话题。伪装可以让你的爬虫看起来更像普通的浏览器或者应用程序,从而减少被服务器封禁的风险;反“反爬”则是应对服务器加强的反爬虫机制。下面将详细介绍一些常见的伪装和反反爬技巧,并提…...
vue3 使用 element-china-area-data 实现地区选择器
官方地址:https://www.npmjs.com/package/element-china-area-data?activeTabreadme 在线示例:https://plortinus.github.io/element-china-area-data/index.html 实际使用 <el-col :span"12"><el-form-item label"所处城市&…...

STM32自带的DSP库的滤波初体验(一)
最近在弄STM32自带的DSP库里的滤波,记录一下: arm_fir_instance_q15 instance_q15_S; #define NUM_TAPS 16 //滤波系数的个数 #define BLOCK_SIZE 32 q15_t firStateF32[BLOCK_SIZE NUM_TAPS]; q15_t Fir_Coeff[NUM_TAPS] {-79, -136, 312, 6…...
go kratos protobuf 接收动态JSON数据
前言 google.protobuf.Struct 是 Google Protocol Buffers 中的一种特殊类型,用于表示动态的键值对数据。它可以存储任意类型的数据,并提供了方便的方法来访问和操作这些数据。 Struct 类型通常用于在不事先知道数据结构的情况下传递和处理配置、参数或其…...
Python学习笔记第五十四天(Pandas DataFrame)
Python学习笔记第五十四天 Pandas 数据结构 - DataFrame使用列表创建使用 ndarrays 创建使用字典创建返回多行数 后记 Pandas 数据结构 - DataFrame DataFrame 是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符…...

Docker镜像查看下载删除镜像文件的相关命令
1.镜像相关命令 本地查看有哪些镜像文件: docker images镜像的名称就是我们常见的一些软件,镜像相当于把软件和软件所需要的运行环境打包到一个镜像文件里面,将来在通过这个镜像文件创建出对应的容器,容器有了以后这些软件自动的…...
1. VisionOS平台介绍
介绍 VisionOS 可实现与现实世界无缝集成并与其他虚拟内容共存的 3D 多任务体验。这为个人生产力、生活方式和娱乐应用打开了一个充满新可能性的世界,并为开发人员打开了一个全新的市场。然而,它也带来了围绕多任务处理和与身体互动的新挑战。Unity Poly…...
【C#】设置有线网卡IP地址,子网掩码,网关,DNS
方法 public partial class ComputerInfo{/// <summary>/// 设置IP地址,子网掩码,网关,DNS/// </summary>public static List<NetworkAdapterInfo> SetIpAddressSubMaskDnsGeteway(string ipAddress, string subMask, stri…...
LVS-DR集群及NGINX负载均衡
LVS-DR集群 原理: 1. 当用户向负载均衡调度器(Director Server)发起请求,调度器将请求发往至内核空间 2. PREROUTING链首先会接收到用户请求,判断目标IP确定是本机IP,将数据包发往INPUT链 3. IPVS是工作在…...

React如何配置env环境变量
React版本: "react": "^18.2.0" 1、在package.json平级目录下创建.env文件 2、在‘.env’文件里配置环境变量 【1】PUBLIC_URL 描述:编译时文件的base-href 官方描述: // We use PUBLIC_URL environment variable …...

VR全景智慧文旅,用科技助力旅游业振兴
引言: 近年来,科技的迅猛发展将我们带入一个全新的数字化时代,而虚拟现实(Virtual Reality,简称VR)技术则以其令人惊叹的全新方式,影响着各个领域。其中,旅游业作为人们探索世界、体…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...

均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...