11 结构型模式- 代理模式
结构性模式一共包括七种:
代理模式、桥接模式、装饰者模式、适配器模式、门面(外观)模式、组合模式、和享元模式。

1 代理模式介绍

软件开发中的代理:
代理模式中引入了一个新的代理对象,代理对象在客户端对象和目标对象之间起到了中介的作用,它去掉客户不能看到的内容和服务或者增加客户需要的额外的新服务.

2 代理模式原理

3 静态代理实现

举例:保存用户功能的静态代理实现
public interface IUserDao {void save();
}
/*** 目标类**/
public class UserDaoImpl implements IUserDao {@Overridepublic void save() {System.out.println("保存数据");}
}
/*** 代理类**/
public class UserDaoProxy implements IUserDao {private IUserDao target;public UserDaoProxy(IUserDao target) {this.target = target;}@Overridepublic void save() {System.out.println("开启事务"); //扩展额外的功能target.save();System.out.println("提交事务");}
}
/*** 静态代理* 优点: 可以在不修改目标类的前提下,扩展目标类的功能* 缺点:* 1.冗余.由于代理对象要实现和目标对象一致的接口,会产生很多的代理.* 2.不易维护.一旦接口中增加方法,目标对象和代理对象都要进行修改.*/@Testpublic void testStaticProxy(){//目标类IUserDao dao = new UserDaoImpl();//代理对象UserDaoProxy proxy = new UserDaoProxy(dao);proxy.save();}
4 JDK动态代理


举例:保存用户功能的静态代理实现
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** 代理工厂类-动态的生成代理对象**/
public class ProxyFactory {//维护一个目标对象private Object target;public ProxyFactory(Object target) {this.target = target;}//为目标对象生成代理对象public Object getProxyInstance(){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("开启事务");method.invoke(target,args);System.out.println("提交事务");return null;}});}
}
测试:
public static void main(String[] args) {IUserDao userDao = new UserDaoImpl();System.out.println(userDao.getClass()); //目标对象的信息IUserDao proxy = (IUserDao) new ProxyFactory(userDao).getProxyInstance();//获取代理对象System.out.println(proxy.getClass());proxy.save();//代理方法while (true){}}
5 类是如何动态生成的



6代理类的调用过程
我们通过借用阿里巴巴的一款线上监控诊断产品 Arthas(阿尔萨斯) ,对动态生成的代理类代码进行查看.


代理类代码如下:
package com.sun.proxy;import com.mashibing.proxy.example01.IUserDao;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;public final class $Proxy0 extends Proxy implements IUserDao {private static Method m1;private static Method m3;private static Method m2;private static Method m0;public $Proxy0(InvocationHandler invocationHandler) {super(invocationHandler);}static {try { m1 = Class.forName("java.lang.Object").getMethod("equals",Class.forName("java.lang.Object"));m3 = Class.forName("com.mashibing.proxy.example01.IUserDao").getMethod("save", new Class[0]);m2 = Class.forName("java.lang.Object").getMethod("toString", newClass[0]);m0 = Class.forName("java.lang.Object").getMethod("hashCode", newClass[0]);return;}catch (NoSuchMethodException noSuchMethodException) {throw new NoSuchMethodError(noSuchMethodException.getMessage());}catch (ClassNotFoundException classNotFoundException){throw new NoClassDefFoundError(classNotFoundException.getMessage());}}public final boolean equals(Object object) {try {return (Boolean)this.h.invoke(this, m1, newObject[]{object});}catch (Error | RuntimeException throwable) {throw throwable;}catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}public final String toString() {try {return (String)this.h.invoke(this, m2, null);}catch (Error | RuntimeException throwable) {throw throwable;}catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}public final int hashCode() {try {return (Integer)this.h.invoke(this, m0, null);}catch (Error | RuntimeException throwable) {throw throwable;}catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}public final void save() {try {this.h.invoke(this, m3, null);return;}catch (Error | RuntimeException throwable) {throw throwable;}catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}
}
爲了方便理解简化后的代码:
package com.sun.proxy;import com.mashibing.proxy.example01.IUserDao;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;public final class $Proxy0 extends Proxy implements IUserDao {private static Method m3;public $Proxy0(InvocationHandler invocationHandler) {super(invocationHandler);}static {try {m3 = Class.forName("com.mashibing.proxy.example01.IUserDao").getMethod("save", new Class[0]);return;}}public final void save() {try {this.h.invoke(this, m3, null);return;}}
}

7 cglib动态代理


使用cglib 需要引入cglib 的jar包,如果你已经有spring-core的jar包,则无需引入,因为spring中包含了cglib 。
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.2.5</version>
</dependency>
示例代码
目标类:
/*** 目标类**/
public class UserServiceImpl {//查询功能public List<User> findUserList(){return Collections.singletonList(new User("tom",23));}
}
cglib代理类,需要实现MethodInterceptor接口,并指定代理目标类target
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Calendar;
//在實現動態代理的同時擴展一個日志的功能
public class UserLogProxy implements MethodInterceptor {/*** 生成CGLIB动态代理类方法* @param target 需要被代理的目标类* @return: java.lang.Object 代理类对象*/public Object getLogProxy(Object target){//增强器类,用来创建动态代理类Enhancer enhancer = new Enhancer();//设置代理类的父类字节码对象enhancer.setSuperclass(target.getClass());//设置回调enhancer.setCallback(this);//创建动态代理对象,并返回return enhancer.create();}/*** 实现回调方法* @param o 代理对象* @param method 目标对象中的方法的Method实例* @param args 实际参数* @param methodProxy 代理类对象中的方法的Method实例* @return: java.lang.Object*/@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Calendar instance = Calendar.getInstance();SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println(format.format(instance.getTime()) + "[ " +method.getName() +"] 查询用户信息...");Object result = methodProxy.invokeSuper(o, args);return null;}
}
public class User {private String name;private int age;public User(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}
}
8 cglib代理流程

9代理模式总结



參考文章:
https://www.cnblogs.com/hg-blogs/p/17314887.html
相关文章:
11 结构型模式- 代理模式
结构性模式一共包括七种: 代理模式、桥接模式、装饰者模式、适配器模式、门面(外观)模式、组合模式、和享元模式。 1 代理模式介绍 软件开发中的代理: 代理模式中引入了一个新的代理对象,代理对象在客户端对象和目标对象之间起到了中介的作用,它去掉客…...
Unity--用户界面
目录 “使用工具栏”: “层次结构”窗口: 层次结构窗口 制作子GameObject “游戏”视图: “场景视图“: ”项目窗口“: 项目窗口工具栏: "Inspector" 窗口: Inspector 游戏…...
BUUCTF 乌镇峰会种图 1
BUUCTF:https://buuoj.cn/challenges 题目描述: 乌镇互联网大会召开了,各国巨头汇聚一堂,他们的照片里隐藏着什么信息呢?(答案格式:flag{答案},只需提交答案࿰…...
Runner GoUI自动化测试发布
构建自动化测试体系是当下每个项目团队愿意去做的,自动化测试减少重复操作节省人力成本。 RunnerGo UI自动化平台 RunnerGo提供从API管理到API性能再到可视化的API自动化、UI自动化测试功能模块,覆盖了整个产品测试周期。 RunnerGo UI自动化基于Selen…...
【Gensim概念】03/3 NLP玩转 word2vec
第三部分 对象函数 八 word2vec对象函数 该对象本质上包含单词和嵌入之间的映射。训练后,可以直接使用它以各种方式查询这些嵌入。有关示例,请参阅模块级别文档字符串。 类型 KeyedVectors 1) add_lifecycle_event(event_name, log_level2…...
【网络协议】聊聊网络路由相关算法
如何配置路由 路由器是一台网络设备,多张网卡,当一个入口的网络包到达路由器时,会根据本地的信息库决定如何正确的转发流量,通常称为路由表 路由表主要包含如下 核心思想是根据目的 IP 地址来配置路由 目的网络:要去…...
Python 深度学习入门之CNN
CNN 前言一、CNN简介1、简介2、结构 二、CNN简介1、输出层2、卷积层3、池化层4、全连接层5、输出层 前言 1024快乐!1024快乐!今天开新坑,学点深度学习相关的,说下比较火的CNN。 一、CNN简介 1、简介 CNN的全称是Convolutiona…...
国产开发板上打造开源ThingsBoard工业网关--基于米尔芯驰MYD-JD9X开发板
本篇测评由面包板论坛的优秀测评者“JerryZhen”提供。 本文将介绍基于米尔电子MYD-JD9X开发板打造成开源的Thingsboard网关。 Thingsboard网关是一个开源的软件网关,采用python作为开发语言,可以部署在任何支持 python 运行环境的主机上,灵…...
英语——语法——从句——名词性从句——笔记
文章目录 名词性从句一、定义二、分类(一)宾语从句(二)主语从句(三)C同位语从句(四)D表语从句 名词性从句 一、句子成分 简而言之,构成一个句子的成分(或要素…...
PROSTATEx-2 上前列腺癌的 3D CNN 分类
内容 本文介绍了在多参数 MRI 序列上使用 3D CNN 对前列腺癌进行显着性或不显着性分类。内容如下: 数据集描述Dicom 到 Nifti 文件格式的转换不同 MRI 序列的联合配准...
npm ERR! node-sass@6.0.1 postinstall: `node scripts/build.js`
1.遇到的问题 vue npm install提示以下错误 2.首次尝试方法 尝试用下面的方式重新安装弄得-saas,结果不起作用 。 npm config set sass_binary_sitehttps://npm.taobao.org/mirrors/node-sass npm install node-sass 这时考虑降级node版本,node.js从…...
3D学习论文参考-ACCURATE EYE PUPIL LOCALIZATION USING HETEROGENEOUS CNN MODELS
以下是该文档的关键内容: 该论文提出了一种使用异构卷积神经网络(CNN)模型的精确眼睛瞳孔定位算法。这种算法可以抵抗光照、图像分辨率和眼镜佩戴等干扰条件,同时具有高准确性。该算法由两部分组成:一是找到近似眼睛区…...
迁移conda环境后,非root用户执行pip命令和jupyter命令报错/bad interpreter: Permission denied
移动conda环境,在移动的环境执行pip和jupyter 报错-bash: /data/home/用户名/anaconda3/envs/llm/bin/pip: /root/anaconda3/envs/llm/bin/python: bad interpreter: Permission denied 报错信息 一、原因 原因是当前的这个data/home/用户名/anaconda3/envs/环境名…...
虚拟机使用linux常用问题(虚拟机操作系统:ubuntu 22.04LTS)
1.虚拟机连接外网 ubuntu解决网络连接的解决方案 CentOS7联网问题解决 明明连接好了但是没有网络的情况 2.虚拟机磁盘扩容 相关博客 利用gparted工具时,直接将unallocated空间的前一个位置的磁盘resize,将unallocated的空间全部覆盖 3.虚拟机与本机共享文件 安装vmtools 设…...
编译原理-词法分析器
文章目录 对于词法分析器的要求概念词法分析器的功能和输出形式 词法分析器的设计词法分析器的结构单词符号的识别:超前搜索状态转换图 正规表达式和有限自动机正规式和正规集确定有限自动机(DFA)非确定有限自动机(NFA)…...
Kafka与MySQL的组合使用
根据上面给出的student表,编写Python程序完成如下操作: (1)读取student表的数据内容,将其转为JSON格式,发送给Kafka; 创建Student表的SQL语句如下: create table student( sno ch…...
2018年亚太杯APMCM数学建模大赛A题老年人平衡能力的实时训练模型求解全过程文档及程序
2018年亚太杯APMCM数学建模大赛 A题 老年人平衡能力的实时训练模型 原题再现 跌倒在老年人中很常见。跌倒可能会导致老年人出现许多并发症,因为他们的康复能力通常较差,因此副作用可能会使人衰弱,从而加速身体衰竭。此外,对跌倒…...
华盛顿特区选举委员会:黑客可能已侵入整个选民名册
导语 近日,华盛顿特区选举委员会(DCBOE)传来了一条令人担忧的消息:黑客可能已经侵入了整个选民名册。这一事件引发了公众的广泛关注和担忧。本文将为大家详细介绍这一事件的经过以及可能带来的后果,并探讨选民数据的保…...
kali安装nodejs、npm失败
更新apt-get再安装,更新时间比较久,看网速,中间有一些确认步骤 22 apt-get update23 apt-get upgrade24 apt-get install nodejs25 node26 npm27 apt-get install npm...
插入排序(学习笔记)
插入排序 每一轮插入排序后的结果与打扑克牌取牌原理相似,将取到的牌插入到合适的位置,但在程序实现方面还是基于交换的算法。 它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。 import java.util.…...
手把手教你用STM32CubeMX和HAL库驱动DW3000:从SPI配置到第一个测距Demo
零基础玩转DW3000:STM32CubeMXHAL库实现厘米级UWB测距全指南 当我们需要在仓库里快速定位某个货架上的商品,或是让扫地机器人精准识别家具位置时,传统GPS和蓝牙方案的精度往往捉襟见肘。这正是UWB(超宽带)技术大显身手…...
Android 14 ShellTransitions 实战:手把手教你理解 Transition 如何“抓取”动画参与者(WindowContainer 篇)
Android 14 ShellTransitions 深度解析:WindowContainer 动画参与者捕获机制实战指南 在 Android 14 的动画框架革新中,ShellTransitions 引入了一套精密的"参与者捕获"系统,其运作机制堪比特种部队的精准行动。本文将带您深入这套…...
01_Neo4j知识体系之原生图数据库架构全景与技术定位
01_Neo4j知识体系之原生图数据库架构全景与技术定位 体系 基础概念层:原生图数据库定位、属性图模型、索引自由邻接、与关系型数据库对比延伸阅读方向:Cypher 查询、图数据科学、向量索引、GraphRAG、企业级集群适用对象:架构师、数据平台负…...
SECS协议实战:从报警触发到Trace数据采集的完整指南
1. SECS协议基础与报警管理实战 半导体设备通信领域有个"隐形语言"叫SECS/GEM协议,它就像设备间的摩斯密码。今天咱们重点聊聊其中两个高频功能:报警管理(S5F1)和Trace数据采集(S2F23/S6F1)。先看…...
Ni8mare高危漏洞来袭:黑客可远程劫持n8n服务器(CVE-2026-21858)
研究人员最新发现,一项被命名为Ni8mare的最高严重级漏洞(CVSS评分10.0),允许远程未授权攻击者完全接管本地部署的n8n工作流自动化平台。该漏洞编号为CVE-2026-21858。据研究人员披露,互联网上存在超过10万台易受攻击的…...
PHP反序列化漏洞实战:从NewStarCTF题目看私有属性的坑
PHP反序列化漏洞实战:私有属性处理中的隐藏陷阱 在CTF竞赛和实际渗透测试中,PHP反序列化漏洞一直是Web安全领域的重点研究对象。而其中关于类属性可见性(特别是private修饰符)的处理机制,往往成为解题的关键突破口。去…...
别再只看电流了!航模电调(ESC)的隐藏功能与安全机制深度解读
航模电调(ESC)的隐藏功能与安全机制深度解析 当你的航模飞机在高速俯冲时突然失去动力,或是悬停表演中电机莫名停转,这些惊险时刻往往与电调的保护机制密切相关。大多数玩家只把电调当作简单的"油门开关",却…...
ai辅助开发:让快马智能体为你规划与优化openclaw本地部署方案
AI辅助开发:让快马智能体为你规划与优化OpenClaw本地部署方案 最近在尝试本地部署OpenClaw项目时,发现这个任务远比想象中复杂。作为一个资源有限的小型开发者,如何在有限的GPU内存环境下运行这个项目成了大难题。好在发现了InsCode(快马)平…...
BetterJoy 完整指南:让Switch手柄成为你的PC游戏利器
BetterJoy 完整指南:让Switch手柄成为你的PC游戏利器 【免费下载链接】BetterJoy Allows the Nintendo Switch Pro Controller, Joycons and SNES controller to be used with CEMU, Citra, Dolphin, Yuzu and as generic XInput 项目地址: https://gitcode.com/g…...
告别手动配置,用快马平台实现openclaw多环境高效部署
最近在折腾openclaw项目部署时,发现环境配置真是个让人头疼的问题。每次切换开发、测试、生产环境都要手动改配置,不仅容易出错,还特别浪费时间。后来尝试用InsCode(快马)平台的自动化部署功能,终于找到了高效的解决方案。 环境配…...
