代理模式实现

一、概念:代理模式属于结构型设计模式。客户端不能直接访问一个对象,可以通过代理的第三者来间接访问该对象,代理对象控制着对于原对象的访问,并允许在客户端访问对象的前后进行一些扩展和处理;这种设置模式称为代理模式;

2个点:

由代理对象去控制对原对象的访问(方法调用),客户端不直接对原对象进行访问,比如数据库的访问,不由Controller去控制;

在访问原对象时,可以有代理对象对原对象的功能(方法)进行扩展,比如访问数据库时,可以在代理对象里面进行开启事务和提交事务或回滚事务;

二、UML类图:

三、实现

1、静态代理实现

/*** Subject*/
public interface IUserMapperInterface {void save(String userName, String userNumber);
}

/*** RealSubject*/
public class UserMapperInterfaceImpl implements IUserMapperInterface {@Overridepublic void save(String userName, String userNumber) {System.out.println("执行insert语句,保存数据,并返回成功!");}
}

/*** 代理类*/
public class UserMapperInterfaceProxy implements IUserMapperInterface {private IUserMapperInterface userMapperInterface;public UserMapperInterfaceProxy(IUserMapperInterface userMapperInterface) {this.userMapperInterface = userMapperInterface;}@Overridepublic void save(String userName, String userNumber) {System.out.println("开启事务~~~");userMapperInterface.save(userName, userNumber);System.out.println("提交事务");}
}

/*** 客户端*/
public class Client {public static void main(String[] args) {String userName = "user name";String userNumber = "user number";UserMapperInterfaceProxy proxy = new UserMapperInterfaceProxy(new UserMapperInterfaceImpl());proxy.save(userName, userNumber);}
}

优缺点:

优点:可以在不修改目标类的前提下,对目标类进行扩展

缺点:

代码冗余,代理对象实现了和目标对象一致的接口,产生了一些冗余接口;

一旦目标接口中增加了新的方法,那么代理对象和真实接口实现都需要修改代码才行;

2、动态代理的实现:

动态代理与静态代理的区别:

静态代理在类加载完经已经加载JVM中,并且如有其他对象需要加载,需要修改代理对象;

动态代理只有在运行的时候才会去加载目标类, 当需要加载其他对象的时候,不需要修改,也就是动态代理可以代理任何对象Object;

动态代理有两种实现方式:JDK动态代理,和CGLib动态代理

  • JDK的动态代理,通过动态的生成一个接口对象的实现实例来实现对接口对象实例的功能扩展,在JDK的动态代理实现中,目标对象必须实现一个接口;
  • 通过反射包下的Proxy.newProxyInstance()方法实现

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 getTargetInstance() {//Proxy是反射包下(java.lang.reflect)的一个代理类,通过这个类的newProxyInstance(新建代理对象实例)来动态的加载一个代理目标对象,并返回//newProxyInstance方法需要传递三个参数,1、目标对象的类加载器, 2、目标对象实现的接口(如果有实现就有,没有实现就没有),3、目标对象需要执行的方法,相当于扩展静态代理中的那个save方法return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {//,目标对象被代理后需要执行的扩展方法,也有三个参数,1、目标对象,2、目标对象需要执行的方法实例,3、方法实例需要传递的参数@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("开启一个事务~!");//执行方法,执行的时候把目标对象和方法参数传递过去method.invoke(target, args);System.out.println("提交事务");//返回值是指目标执行的方法的返回值,如果没有就返回null,在静态代理中,目标方法save的返回值是void,因此这里返回nullreturn null;}});}
}

/*** 客户端*/
public class Client {public static void main(String[] args) {String userName = "user name";String userNumber = "user number";//使用静态代理的模式实现代理,此时在类加载的时候就会创建该对象UserMapperInterfaceProxy proxy = new UserMapperInterfaceProxy(new UserMapperInterfaceImpl());proxy.save(userName, userNumber);System.out.println("静态代理实现的类名:" + proxy.getClass().getName());//使用动态代理的模式实现代理功能,在类加载的时候不会创建对象,在运行过程中才会去创建对象并调用对象 的方法ProxyFactory proxyFactory = new ProxyFactory(new UserMapperInterfaceImpl());IUserMapperInterface targetInstance = (IUserMapperInterface) proxyFactory.getTargetInstance();targetInstance.save(userName, userNumber);System.out.println("动态代理实现的类名:" + targetInstance.getClass().getName());}
}
  • CGLib动态代理的实现

CGLib是一个第三方的代码生成类库,运行时在内存中生成一个子类继承目标对象,从而实现对目标对象的扩展;SpringAOP和Hibernate都是基于CGLib动态代理实现的,而CGlib又是通过封装ASM工具包去操作字节码的;

引入包:如果是Spring项目,则不需要单独引入,SpringCore里面已经包含该包

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

目标类:


/*** CGLib方式实现代理的目标类*/
public class CGLibTargetClass {public void targetMethod(String userName, String userNumber) {System.out.println("CGLibTargetClass targetMethod");System.out.println("保存用户信息:username=" + userName + ",usernumber=" + userNumber);}
}

代理类:实现MethodInterceptor接口,并重写interceptor方法,

public class CGLibProxyIntercept implements MethodInterceptor {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("保存用户信息前开启事务");System.out.println(objects.toString());System.out.println(o.getClass().getName());methodProxy.invokeSuper(o, objects);System.out.println("保存用户信息后提交事务");return o;}
}

代理模式的总结:

由于CGlib采用的是继承目标类的方式去进行增强的,因此对于final类或方法是不能被继承的,无法使用CGlib的方式进行代理;

在jdk1.8后,实际上JDK动态代理比CGLib动态代理效率高,但JDK动态代理需要目标类实现一个接口,因此如果对象有实现接口,用JDK动态代理,没实现 用CGLib动态代理;

有缺点:

在客户端与目标对象之间起到中介作用,保护目标对象

对目标对象进行扩展,将客户端与目标对象分离,解耦

增加系统复杂度

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

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

相关文章

windows 搭建flutter环境,开发windows程序

环境安装配置&#xff1a; 下载flutter sdk https://docs.flutter.dev/get-started/install/windows 下载到本地后&#xff0c;随便找个地方解压&#xff0c;然后配置下系统环境变量 编译windows程序本地需要安装vs2019或更新的开发环境 主要就这2步安装后就可以了&#xff0…

Redis系列之底层数据结构字典Dict

Redis系列之底层数据结构字典Dict Dict数据结构 Dict是Redis数据结构中使用最为频繁的复合型数据结构&#xff0c;本质上是一个哈希表 查看redis6.0版本的源码&#xff0c;链接&#xff1a;https://github.com/redis/redis/blob/6.0/src/dict.h 哈希表的结构定义&#xff1…

【Azure 架构师学习笔记】- Azure Function (2) --实操1

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Function 】系列。 接上文【Azure 架构师学习笔记】- Azure Function (1) --环境搭建和背景介绍 前言 上一文介绍了环境搭建&#xff0c;接下来就在本地环境下使用一下。 环境准备 这里我下载了最新的VS studio&…

【NextJS】PostgreSQL 遇上 Prisma ORM

NextJS 数据库 之 遇上Prisma ORM 前言一、环境要求二、概念介绍1、Prisma Schema Language&#xff08;PSL&#xff09; 结构描述语言1.1 概念1.2 组成1.2.1 Data Source 数据源1.2.2 Generators 生成器1.2.3 Data Model Definition 数据模型定义字段(数据)类型和约束关系&…

左神算法基础提升--3

文章目录 Manacher 算法经典算法Manacher算法原理 单调栈或单调队列 Manacher 算法 经典算法 在每学习Manacher算法之前我们可能会使用一种比较经典暴力的算法&#xff1a;遍历str字符串&#xff0c;将字符串中的每个字符作为对称点&#xff0c;向两边扩散找到回文字段&#x…

浅谈操作系统与初识Linux

一、Linux操作系统的出现 1.1操作系统的出现以及相关的四个要素 1.2最早出现的操作系统及其创始人 起初&#xff0c;IBM为了让计算机可以以更低技术成本进行使用&#xff0c;以此来售卖计算机&#xff1b; 为计算机搭载上了Unix操作系统&#xff0c;Unix由肯汤普森用汇编语…

ElasticSearch下

DSL查询 叶子查询&#xff1a;在特定字段里查询特定值&#xff0c;属于简单查询&#xff0c;很少单独使用复合查询&#xff1a;以逻辑方式组合多个叶子查询或更改叶子查询的行为方式 在查询后还可以对查询结果做处理&#xff1a; 排序&#xff1a;按照1个或多个字段做排序分页…

java根据模板导出word,并在word中插入echarts相关统计图片以及表格

引入依赖创建word模板创建ftl模板文件保存的ftl可能会出现占位符分割的问题&#xff0c;需要处理将ftl文件中的图片的Base64删除&#xff0c;并使用占位符代替插入表格&#xff0c;并指定表格的位置在图片下方 Echarts转图片根据模板生成word文档DocUtil导出word文档 生成的wor…

链式前向星的写法

【图论02】动画说图的三种保存方式 降低理解门槛 邻接表 链式前向星 邻接矩阵_哔哩哔哩_bilibili 杭电ACM刘老师-算法入门培训-第12讲-拓扑排序及链式前向星_哔哩哔哩_bilibili 图论003链式前向星_哔哩哔哩_bilibili&#xff08;链式前向星的遍历&#xff09; head数组的下标…

想品客老师的第一天:值类型使用

前面两章的摘要 ECMAscript&#xff08;也就是ES&#xff09;是JavaScript的一个标准&#xff0c;就像c的c11和c99一样&#xff0c;几把的一年出一套标准 freeze()是一个对象方法&#xff0c;表示锁定、固定一个对象不可改变&#xff08;因为const对于标量不可变&#xff0c;…

贪心算法(题1)区间选点

输出 2 #include <iostream> #include<algorithm>using namespace std;const int N 100010 ;int n; struct Range {int l,r;bool operator <(const Range &W)const{return r<W.r;} }range[N];int main() {scanf("%d",&n);for(int i0;i&l…

解决本地运行MR程序访问权限问题

文章目录 1. 提出问题2. 解决问题2.1 临时解决方案2.2 永久解决方案 3. 小结 1. 提出问题 运行DeduplicateIPsDriver类&#xff0c;抛出如下异常&#xff1a; 该错误信息表明在尝试运行 DeduplicateIPsDriver 类时&#xff0c;遇到了 HDFS&#xff08;Hadoop 分布式文件系统&a…

html全局遮罩,通过websocket来实现实时发布公告

1.index.html代码示例 <div id"websocket" style"display:none;position: absolute;color:red;background-color: black;width: 100%;height: 100%;z-index: 100; opacity: 0.9; padding-top: 30%;padding-left: 30%; padding-border:1px; "onclick&q…

高通8255 Android STR 启动失败要因分析调查

目录 背景&#xff1a; 调查过程&#xff1a; 步骤1&#xff1a; slog2info | grep vmm_service 步骤2&#xff1a; slog2info | grep qvm 总结&#xff1a; 解决方案 背景&#xff1a; 调试高通8255 STR的STR过程中发现Android和QNX进入STR状态后&#xff0c;脱出STR时…

Linux UDP 编程详解

一、引言 在网络编程领域&#xff0c;UDP&#xff08;User Datagram Protocol&#xff0c;用户数据报协议&#xff09;作为一种轻量级的传输层协议&#xff0c;具有独特的优势和适用场景。与 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff0…

可解释性机器学习

一、引言 随着机器学习&#xff08;ML&#xff09;在各个领域的广泛应用&#xff0c;模型的复杂度不断增加&#xff0c;如深度神经网络等黑盒模型逐渐成为主流。这些模型虽然具有很高的预测性能&#xff0c;但其内部的决策机制往往难以理解&#xff0c;导致模型的透明度和可解释…

PyTorch使用教程(8)-一文了解torchvision

一、什么是torchvision torchvision提供了丰富的功能&#xff0c;主要包括数据集、模型、转换工具和实用方法四大模块。数据集模块内置了多种广泛使用的图像和视频数据集&#xff0c;如ImageNet、CIFAR-10、MNIST等&#xff0c;方便开发者进行训练和评估。模型模块封装了大量经…

网络安全防护指南:筑牢网络安全防线(510)

一、网络安全的基本概念 &#xff08;一&#xff09;网络的定义 网络是指由计算机或者其他信息终端及相关设备组成的按照一定的规则和程序对信息收集、存储、传输、交换、处理的系统。在当今数字化时代&#xff0c;网络已经成为人们生活和工作中不可或缺的一部分。它连接了世…

关于vite+vue3+ts项目中env.d.ts 文件详解

env.d.ts 文件是 Vite 项目中用于定义全局类型声明的 TypeScript 文件。它帮助开发者向 TypeScript提供全局的类型提示&#xff0c;特别是在使用一些特定于 Vite 的功能时&#xff08;如 import.meta.env&#xff09;。以下是详细讲解及代码示例 文章目录 **1. env.d.ts 文件的…

1.17学习

crypto nssctf-[SWPUCTF 2021 新生赛]crypto8 不太认识这是什么编码&#xff0c;搜索一下发现是一个UUENCODE编码&#xff0c;用在线工具UUENCODE解码计算器—LZL在线工具解码就好 misc buuctf-文件中的秘密 下载附件打开后发现是一个图片&#xff0c;应该是一个图片隐写&…