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.…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
