Java设计模式-结构型模式-代理模式

代理模式

  • 代理模式
    • 静态代理
    • 动态代理
      • JDK动态代理
      • CGlib动态代理

代理模式

创建一个代理对象来控制对原始对象的访问,可以用来扩展原始对象的功能,同时保护原始对象
一般使用代理模式的目的有两个:

  1. 保护目标对象
  2. 增强目标对象

代理模式有两种实现方案:静态代理 和 动态代理
在这里插入图片描述
下面以Dao层执行sql语句为例,讲述代理模式的 应用

静态代理

静态代理就是通过组合/继承的方式,代理类关联原始类,通过调用代理类的方法来实现 原始类的方法增强
这里有一个UserDaoImpl,作为原始类,提供一个模拟插入用户的接口

public interface UserDao {void insert();
}
/*****************************************************/public class UserDaoImpl implements UserDao{public void insert(){System.out.println("插入一个用户");}
}

创建一个静态代理类,StaticProxyUserDao,完成对userDao的增强

public class StaticProxyUserDao implements UserDao{private UserDao userDao;public StaticProxyUserDao(UserDao userDao) {this.userDao = userDao;}@Overridepublic void insert(){//事务开启...System.out.println("事务开启");userDao.insert();//方法增强...//事务提交...System.out.println("事务提交");}
}

测试代码如下,很容易理解,就不解释了

@Test
public void staticProxyTest(){//直接使用UserDao userDao = new UserDaoImpl();userDao.insert();System.out.println("---------------------------------------------------");//通过静态代理的方式,增强insert()方法StaticProxyUserDao staticProxyUserDao = new StaticProxyUserDao(userDao);staticProxyUserDao.insert();
}输出:
插入一个用户
---------------------------------------------------
事务开启
插入一个用户
事务提交

动态代理

通过静态代理的方式可以实现方法的增强,但对于每个增强的类,都需要再写一个代理类,这样显得代码比较臃肿,所以就有了动态代理,可以在程序执行过程中,动态的代理目标类。

动态代理有两种实现方式:JDK动态代理CGlib动态代理

JDK动态代理

JDK动态代理是Java标准库中提供的一种代理方式
JDK动态代理是依赖接口的。
实现方式:通过Proxy类中的 静态方法 newProxyInstance(…)实现

@Test
public void JdkProxyTest(){UserDao userDao = new UserDaoImpl();/** 参数1:指定一个类加载器* 参数2:指定接口 getInterfaces()* 参数3:指定对应的代理方法* */System.out.println();UserDao proxyUserDao = (UserDao)Proxy.newProxyInstance(UserDao.class.getClassLoader(), UserDaoImpl.class.getInterfaces(), (proxy, method, args) -> {System.out.println("事务开启");Object invoke = method.invoke(userDao,args);System.out.println("事务关闭");return invoke;});proxyUserDao.insert();
}

可以看出来,JDK动态代理的方法 必须在接口中有定义,所以,如果想要代理没有在接口中定义的方法,这就需要使用CGlib来实现

CGlib动态代理

CGlib 是基于 类继承实现的,通过继承目标类 来实现类的代理,所以目标类必须是可继承的
CGlib支持更细粒度的代理——针对某个方法进行代理
CGLIB是第三方提供的包,需要引入Jar包

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.1</version>
</dependency>

spring-core jar包里包含cglib ,所以使用spring框架的工程可以直接使用。
实现方式:通过Enhancer类实现,如下:

@Test
public void CGlibProxyTest(){// 创建Enhancer对象 类似于 Proxy类Enhancer enhancer = new Enhancer();// 设置父类的字节码对象 即需要代理的类enhancer.setSuperclass(UserDaoImpl.class);//设置回调函数,增强方法/*** o 代理对象,即生成的代理类的实例,这里是生成的代理对象,不是被代理对象* method 被代理方法的Method对象* args 方法调用时传递的参数数组* methodProxy 方法代理对象*/enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {System.out.println("事务开启");//这里注意使用的是 invokeSuper() 调用的是父类的接口Object invoke = methodProxy.invokeSuper(o,objects);System.out.println("事务关闭");return invoke;});// 生成代理对象UserDaoImpl proxy = (UserDaoImpl) enhancer.create();proxy.insert();
}

这里提一下注意的点:

JDK动态代理,依赖接口完成代理,没有实例对象,所以需要传入实例对象,
即 method.invoke(userDao,args); 中的userDao,所以在代理之前,需要先有个实例化的对象

而CGlib动态代理,依赖类继承实现,本身是知道代理对象的所有结构的,所以不需要传入实例对象,所以:
enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
System.out.println(“事务开启”);
Object invoke = methodProxy.invokeSuper(o,objects);
System.out.println(“事务关闭”);
return invoke;
});
第一个参数是 代理对象,而不是被代理对象,调用方法使用的是 invokeSuper() 不是invoke(),调用的是父类的接口

关于CGlib和JDK代理的详细代理过程,可以看下这篇文章
https://blog.csdn.net/ren9436/article/details/125602288

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/141529.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【OpenCV实现图像:用OpenCV图像处理技巧之巧用直方图】

文章目录 概要前置条件统计数据分析直方图均衡化原理小结 概要 图像处理是计算机视觉领域中的重要组成部分&#xff0c;而直方图在图像处理中扮演着关键的角色。如何巧妙地运用OpenCV库中的图像处理技巧&#xff0c;特别是直方图相关的方法&#xff0c;来提高图像质量、改善细…

stm32超声波测距不准的解决方法(STM32 delay_us()产生1us)及stm32智能小车超声波测距代码(C语言版本)

首先要说明一下原理&#xff1a;使用stm32无法准确产生1us的时间&#xff0c;但是超声波测距一定要依赖时间&#xff0c;时间不准&#xff0c;距离一定不准&#xff0c;这是要肯定的&#xff0c;但是在不准确的情况下&#xff0c;要测量一个比较准确的时间&#xff0c;那么只能…

同一个Unity项目打开两个Unity Editor实例

特殊情况下&#xff0c;同一个项目需要同时打开两个编辑器做测试&#xff0c;如多人在线游戏&#xff0c;或者有通信功能的时候就有这样的需求。同时也为了方便调试和观察日志。并且修改的是同一份代码。 命令介绍&#xff1a; 实现思路&#xff1a; 使用 mklink 命令 分别创建…

使用 huggingface_hub 镜像下载 大模型

download.py &#x1f447; import os # 配置 hf镜像 os.environ[HF_ENDPOINT] https://hf-mirror.com# 设置保存的路径 local_dir "XXXXXX"# 设置仓库id model_id "sensenova/piccolo-large-zh"cmd f"huggingface-cli download --resume-downlo…

【MySQL】库的相关操作 + 库的备份和还原

库的操作 前言正式开始创建数据库删除数据库编码集查看系统默认字符集以及校验规则字符集校验规则 所有支持的字符集和校验规则所有字符集所有校验规则 指明字符集和校验规则创建数据库相同的字符集用不同的校验规则读取会出现什么情况 alter修改数据库show create databasealt…

瑞萨e2studio(29)----SPI速率解析

瑞萨e2studio.29--SPI速率解析 概述视频教学时钟配置解析RA4M2的BRR值时钟速率7.5M下寄存器值3K下寄存器值 概述 在嵌入式系统的设计中&#xff0c;串行外设接口&#xff08;SPI&#xff09;的通信速率是一个关键参数&#xff0c;它直接影响到系统的性能和稳定性。瑞萨电子的…

C# Onnx LSTR 基于Transformer的端到端实时车道线检测

目录 效果 模型信息 项目 代码 下载 效果 模型信息 lstr_360x640.onnx Inputs ------------------------- name&#xff1a;input_rgb tensor&#xff1a;Float[1, 3, 360, 640] name&#xff1a;input_mask tensor&#xff1a;Float[1, 1, 360, 640] -----------------…

适配器模式 rust和java的实现

文章目录 适配器模式介绍何时使用应用实例优点缺点使用场景 实现java实现rust 实现 rust代码仓库 适配器模式 适配器模式&#xff08;Adapter Pattern&#xff09;是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式&#xff0c;它结合了两个独立接口的功能…

【每日一题】区域和检索 - 数组可修改

文章目录 Tag题目来源解题思路方法一&#xff1a;分块方法二&#xff1a;线段树方法三&#xff1a;树状数组 写在最后 Tag 【树状数组】【线段树】【分块】【前缀和】【设计类】【2023-11-13】 题目来源 307. 区域和检索 - 数组可修改 解题思路 使用前缀和解决不行吗&#x…

centos利用find提权反弹shell

需要说明的是利用find命令进行提权的方式已经不存在了&#xff0c;因为Linux默认不会为find命令授予suid权限&#xff0c;这里只是刻意的制造出了一种存在提权的环境 首先我们先介绍一下find命令&#xff0c;find命令主要用来在Linux中查找文件使用&#xff0c;它可以进行最基础…

Brute Force

Brute Force "Brute Force"&#xff08;暴力破解&#xff09;指的是一种通过尝试所有可能的组合来获取访问、解密或破解信息的攻击方法。这种攻击方法通常是基于暴力和不断尝试的&#xff0c;不依赖漏洞或弱点。通常用于破解密码、破坏系统或获取未经授权的访问权限…

数据分析实战 | 逻辑回归——病例自动诊断分析

目录 一、数据及分析对象 二、目的及分析任务 三、方法及工具 四、数据读入 五、数据理解 六、数据准备 七、模型训练 八、模型评价 九、模型调参 十、模型预测 一、数据及分析对象 CSV文件——“bc_data.csv” 数据集链接&#xff1a;https://download.csdn.net/d…

MongoDB基础知识~

引入MongoDB&#xff1a; 在面对高并发&#xff0c;高效率存储和访问&#xff0c;高扩展性和高可用性等的需求下&#xff0c;我们之前所学习过的关系型数据库(MySql,sql server…)显得有点力不从心&#xff0c;而这些需求在我们的生活中也是随处可见的&#xff0c;例如在社交中…

JVM如何运行,揭秘Java虚拟机运行时数据区

目录 一、概述 二、程序计数器 三、虚拟机栈 四、本地方法栈 五、本地方法接口 六、堆 &#xff08;一&#xff09;概述 &#xff08;二&#xff09;堆空间细分 七、方法区 一、概述 不同的JVM对于内存的划分方式和管理机制存在部分差异&#xff0c;后续针对HotSpot虚…

CSS特效007:绘制3D文字,类似PS效果

总第 007 篇文章&#xff0c; 查看专栏目录 本专栏记录的是经常使用的CSS示例与技巧&#xff0c;主要包含CSS布局&#xff0c;CSS特效&#xff0c;CSS花边信息三部分内容。其中CSS布局主要是列出一些常用的CSS布局信息点&#xff0c;CSS特效主要是一些动画示例&#xff0c;CSS花…

2023年数维杯国际大学生数学建模挑战赛A题

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 cs数模团队在数维杯前为大家提供了许多资料的内容呀&#xff0…

贪吃蛇和俄罗斯方块

贪吃蛇 一、创建新项目 创建一个新的项目&#xff0c;并命名。 创建一个名为images的文件夹用来存放游戏相关图片。 然后再在项目的src文件下创建一个com.xxx.view的包用来存放所有的图形界面类&#xff0c; 创建一个com.xxx.controller的包用来存放启动的入口类(控制类) …

重复性工作自动化解决方案——影刀

以前&#xff0c;影刀是一个邂逅的初见小工具&#xff0c;新奇在里头&#xff0c;踌躇在外头&#xff1b; 现在&#xff0c;影刀是一个稳定的职场贾维斯&#xff0c;高效在里头&#xff0c;悠闲在外头&#xff1b; 以后&#xff0c;影刀是一个潜力的知己老司机&#xff0c;有序…

2019年五一杯数学建模A题让标枪飞解题全过程文档及程序

2020年五一杯数学建模 A题 让标枪飞 原题再现 标枪的投掷是一项历史悠久的田径比赛项目。标枪投掷距离的远近受到运动员水平&#xff08;出手速度、出手角、初始攻角、出手高度、出手时标枪的初始俯仰角速度等&#xff09;&#xff0c;标枪的技术参数&#xff08;标枪的长度、…

网络运维Day14

监控概述 监控的目的 报告系统运行状况每一部分必须同时监控内容包括吞吐量、反应时间、使用率等提前发现问题进行服务器性能调整前&#xff0c;知道调整什么找出系统的瓶颈在什么地方 监控的资源类别 公开数据 Web、FTP、SSH、数据库等应用服务TCP或UDP端口 私有数据 CPU、内…