当前位置: 首页 > news >正文

Spring 学习(六)代理模式

10. 代理模式

  • 案例

在这里插入图片描述

10.1 静态代理

  • 角色分析

    • 抽象角色:一般使用接口或者抽象类实现。
    • 真实角色:被代理的角色。
    • 代理角色:代理真实角色,含附属操作。
    • 客户:访问代理对象的角色。
  • 租房案例

    • 定义租赁接口

      /*** TODO* 租房* @author why* @since 2021/7/6 9:06*/
      public interface Rent {public void rent();
      }
      
    • 定义真实角色

      /*** TODO* 房东* @author why* @since 2021/7/6 9:10*/
      public class Landlord implements Rent {public void rent() {System.out.println("房东要出租房子");}
      }
      
    • 定义代理角色

      /*** TODO* 中介* @author why* @since 2021/7/6 9:14*/
      public class Proxy implements Rent {private Landlord landlord;public Proxy() {}public Proxy(Landlord landlord) {this.landlord = landlord;}/*** 出租房子*/public void rent() {seeHouse();landlord.rent();signContract();fee();}/*** 看房*/public void seeHouse(){System.out.println("中介带租客看房");}/*** 收中介费*/public void fee(){System.out.println("收中介费");}/*** 签合同*/public void signContract(){System.out.println("签租赁合同");}}
      
    • 客户端访问代理角色

      /*** TODO* 租客* @author why* @since 2021/7/6 9:12*/
      public class Client {public static void main(String[] args) {// 房东想要出租房子Landlord landlord = new Landlord();// 中介帮助房东出租房子,包含了附加操作Proxy proxy = new Proxy(landlord);// 租客找中介租房子proxy.rent();}
      }
      
  • 模式优点

    • 可以使真实角色的操作更加纯粹,不必关注一些公共业务。
    • 公共业务交给代理角色,实现了业务的分工。
    • 公共业务发生扩展时,方便集中管理。
  • 模式缺点

    • 一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率会变低。
  • 业务模拟

    • 抽象 AOP 机制

      在这里插入图片描述

    • 定义用户操作接口

      /*** TODO* 用户服务接口* @author why* @since 2021/7/6 9:38*/
      public interface UserService {public void add();public void delete();public void update();public void query();
      }
      
    • 定义业务操作实现类

      /*** TODO* 用户接口实现类(真实对象)* @author why* @since 2021/7/6 9:40*/
      public class UserServiceImpl implements UserService {public void add() {System.out.println("增加一个用户");}public void delete() {System.out.println("删除一个用户");}public void update() {System.out.println("修改一个用户");}public void query() {System.out.println("查询一个用户");}
      }
      
    • 定义代理

      /*** TODO* 代理* @author why* @since 2021/7/6 9:57*/
      public class UserServiceProxy implements UserService {private UserService userService;public void setUserService(UserService userService) {this.userService = userService;}public void add() {log("add");userService.add();}public void delete() {log("delete");userService.delete();}public void update() {log("update");userService.update();}public void query() {log("query");userService.query();}// 日志方法public void log(String msg) {System.out.println("[Debug] 使用了"+ msg +"方法");}
      }
      
    • 定义客户端

      /*** TODO* 客户端* @author why* @since 2021/7/6 9:44*/
      public class Client {public static void main(String[] args) {UserServiceImpl userService = new UserServiceImpl();UserServiceProxy userServiceProxy = new UserServiceProxy();userServiceProxy.setUserService(userService);userServiceProxy.add();}
      }
      

10.2 动态代理

  • 动态代理和静态代理的角色一样

  • 动态代理的代理类是动态生成的,不需要编写。

  • 动态代理分为基于接口的动态代理和基于类的动态代理。

    • 基于接口 — JDK 动态代理
    • 基于类 — CGLIB
    • Java 字节码实现 — Javasist
  • 租房案例

    • 定义租赁接口

      /*** TODO* 租房* @author why* @since 2021/7/6 9:06*/
      public interface Rent {public void rent();
      }
      
    • 定义真实角色(房东)

      /*** TODO* 房东* @author why* @since 2021/7/6 9:10*/
      public class Landlord implements Rent {public void rent() {System.out.println("房东要出租房子");}
      }
      
    • 构造代理类生成器

      /*** TODO* 自动生成代理类* @author why* @since 2021/7/6 13:43*/
      public class ProxyInvocationHandler implements InvocationHandler {// 被代理的接口private Rent rent;public void setRent(Rent rent) {this.rent = rent;}// 获得代理类public Object getProxy(){return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);}// 处理代理实例并返回结果public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 动态代理由反射机制实现Object result = method.invoke(rent, args);return result;}
      }
      
    • 定义客户端

      /*** TODO* 客户端* @author why* @since 2021/7/6 13:54*/
      public class Client {public static void main(String[] args) {// 真实角色Landlord landlord = new Landlord();// 代理角色(由 InvocationHandler 获取)ProxyInvocationHandler pih = new ProxyInvocationHandler();// 通过调用处理程序处理要调用的接口对象pih.setRent(landlord);Rent proxy = (Rent) pih.getProxy();proxy.rent();}
      }
      
  • 模式优点

    • 可以使真实角色的操作更加纯粹,不必关注一些公共业务。
    • 公共业务交给代理角色,实现了业务的分工。
    • 公共业务发生扩展时,方便集中管理。
    • 一个动态代理类代理的是一个接口,一般就是一类业务。
    • 一个动态代理可以代理多个类,前提是这些类实现了同一个接口。
  • 业务模拟

    • 定义用户操作接口

      /*** TODO* 用户服务接口* @author why* @since 2021/7/6 9:38*/
      public interface UserService {public void add();public void delete();public void update();public void query();
      }
      
    • 定义业务操作实现类

      /*** TODO* 用户接口实现类(真实对象)* @author why* @since 2021/7/6 9:40*/
      public class UserServiceImpl implements UserService {public void add() {System.out.println("增加一个用户");}public void delete() {System.out.println("删除一个用户");}public void update() {System.out.println("修改一个用户");}public void query() {System.out.println("查询一个用户");}
      }
      
    • 定义代理生成器

      /*** TODO* 自动生成代理类* @author why* @since 2021/7/6 13:43*/
      public class ProxyInvocationHandler implements InvocationHandler {// 被代理的接口private Object target;public void setTarget(Object target) {this.target = target;}// 获得代理类public Object getProxy(){return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}// 处理代理实例并返回结果public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {log(method.getName());// 动态代理由反射机制实现return method.invoke(target, args);}public void log(String msg){System.out.println("执行了" + msg + "方法");}
      }
      
    • 定义客户端

      /*** TODO* 客户端* @author why* @since 2021/7/6 15:00*/
      public class Client {public static void main(String[] args) {UserServiceImpl userService = new UserServiceImpl();ProxyInvocationHandler pih = new ProxyInvocationHandler();pih.setTarget(userService);UserService proxy = (UserService) pih.getProxy();proxy.add();}
      }
      

相关文章:

Spring 学习(六)代理模式

10. 代理模式 案例 10.1 静态代理 角色分析 抽象角色:一般使用接口或者抽象类实现。真实角色:被代理的角色。代理角色:代理真实角色,含附属操作。客户:访问代理对象的角色。 租房案例 定义租赁接口 /*** TODO* 租房*…...

Educational Codeforces Round 155 (Rated for Div. 2) - D Sum of XOR Functions

学到的几个知识点: 1.拆位 对于整体上的异或操作可以转化为31个二进制位上的操作,每一位再上 。 将一次操作拆为31次来方便操作。 2. s[i]表示异或前缀和,l~r间的异或和为s[r] ^ s[l - 1] ----> 拆完位后这个公式还能再推出一个性…...

[C++ 网络协议] I/O流分离所带来的半关闭问题

1.问题和解决方法 根据所学内容,I/O流分离现如今有如下2种方法: 1.调用进程fork函数,分离出子进程,主进程和子进程分别进行输入流的读和输出流的写。 2.用FILE指针按读模式和写模式将输入流和输出流进行区分。 第一种方法&#…...

根据文章段落内容自动插入图片php版

每篇内容根据段落判断插入图片代码附上&#xff1a; $chatd"<table>";if(stripos($content,$chatd)0){//随机输出三张图功能if($moduleid!37 &&$thumb){//判断是否存在图$idrand(1,999999);$midrand(1,9999999);$getimg"http://www.nongpin88.co…...

在GEHC的第一个sprint记录

今天是进入GEHC XR ATX的第25天&#xff0c;是周日&#xff0c;下周二我的第一个sprint也就到期了&#xff0c;幸好在这周五晚上完成了&#xff0c;当然还差个分享。在此记录第一个sprint中两个story过程。 第一个story是操作固定式DR设备进行exposure整个过程。这是所有新人必…...

MFC 绘图

效果图&#xff1a;三张bmp图 字 竖线 组成 在OnPaint()函数中 CPaintDC dc(this);CRect rect;GetClientRect(&rect); //获取客户区矩形CDC dcBmp; //定义并创建一个内存设备环境dcBmp.CreateCompatibleDC(&dc); //创建兼容性DCCBitmap …...

算法 用两个栈实现队列-(栈+队列)

牛客网: BM42 题目: 用两个栈模拟队列 思路: stack1, stack2两个栈&#xff0c;入队只选择stack1, 出队只选择stack2, 如果stack2为空&#xff0c;将stack1元素全部出栈并入栈stack2。 代码: // gopackage mainvar stack1 [] int var stack2 [] intfunc Push(node int) {st…...

Android单编模块报FAILED: ninja: unknown target ‘MODULES-IN-vendor错误解决

有时我们需要单编Android AOSP一个APK或库文件或二进制&#xff0c;用来调试。 但可能这个模块本身是不参与系统整编编译的。我们在使用mmm或mm单独编译时就会报这个错误。 在检查Android.mk或Android.bp无误后&#xff0c;就要怀疑是不是这个目录的上级目录是不是没有包含这…...

地球的某一片红薯地中秋圆《乡村振兴战略下传统村落文化旅游设计》——旅行季许少辉八月新书辉少许想象和世界一样宽广

地球的某一片红薯地中秋圆《乡村振兴战略下传统村落文化旅游设计》——旅行季许少辉八月新书辉少许想象和世界一样宽广 地球的某一片红薯地中秋圆《乡村振兴战略下传统村落文化旅游设计》——旅行季许少辉八月新书辉少许想象和世界一样宽广]...

Zookeeper-命令操作

命令操作 命令操作1) Zookeeper 数据模型2) Zookeeper 服务端常用命令3) Zookeeper 客户端常用命令 命令操作 1) Zookeeper 数据模型 ZooKeeper 是一个树形目录服务,其数据模型和Unix的文件系统目录树很类似&#xff0c;拥有一个层次化结构。 这里面的每一个节点都被称为&am…...

eclipse 添加注释

在 Eclipse 中&#xff0c;你可以使用注释来为你的代码添加说明、文档或标记。以下是如何在 Eclipse 中添加注释的一些方法&#xff1a; 单行注释&#xff1a;你可以使用单行注释来注释一行代码。在要注释的代码行前面添加双斜杠 // 即可。例如&#xff1a; // 这是一个单行注…...

Linux网络编程- 网络字节顺序

基本概念 网络字节顺序是一种规定的数据表示格式&#xff0c;被用于TCP/IP协议栈&#xff0c;特别是在网络传输数据时。它确保不同的计算机和架构之间可以无缝地通信。网络字节顺序是大端字节序&#xff08;big-endian&#xff09;。 字节序的背景 计算机存储多字节数据&…...

如何永久关闭WPS任务窗口?

1、按住任务窗口上的浮动按钮&#xff0c;将其拖出来成悬浮窗口。 第二步&#xff0c;使用火绒弹窗拦截&#xff0c;选中弹出的窗口&#xff0c;进行拦截。注意&#xff1a;拦截次数为2次。即进行2次操作。 操作两次后&#xff0c;弹窗被拦截&#xff0c;此时Word文档改为双页显…...

Cesium 问题:加载 geojson 数据量大浏览器会崩,使用primitive方式加载

文章目录 问题分析 问题 之前加载geojson数据都是使用dataSource和entity的方式&#xff0c;但是当数据量大时&#xff0c;浏览器就会崩掉&#xff1a;提示浏览器内存不足&#xff0c;已暂停渲染 分析 使用primitive方式加载数据&#xff0c;可以提高加载渲染效率。实现方法…...

C++ Primer----1.5类简介 章节练习

头文件 Sales_item.h #ifndef SALESITEM_H #define SALESITEM_H #include <iostream> #include <string>class Sales_item{ public:Sales_item(const std::string &book):isbn(book),units_sold(0),revenue(0.0){}Sales_item(std::istream &is){ is >&…...

爬楼梯Java(斐波那契数列)

题目:有n阶楼梯,一次只能爬一层或者两层,请问有多少种方法? 这类题目其实都可以用斐波那契数列来解决,比如: 一阶楼梯只有一种方法 二阶楼梯有(11,2)两种方法 三阶楼梯有(111,12,21)三种方法 四阶楼梯有(1111,121,112,22,211)五种方式 五阶楼梯有(11111,1112,122,1211,1…...

Maven项目package为jar包后在window运行报A JNI error has occurred

原因&#xff1a;本地java版本与项目结构中使用的java版本不一致&#xff08;之前因为别的需求把idea的java版本改为了18&#xff09; 解决方法 打开项目结构&#xff0c;将idea的java版本改为与本地一致 再修改项目中的pom.xml 重新编译&#xff0c;package即可...

iview 的table表格组件使单元格可编辑和输入

表格的列定义中&#xff0c;在需要编辑的字段下使用render函数 template表格组件 <Table border :data"data" :columns"tableColumns" :loading"loading"></Table>data中定义table对象 table: {tableColumns: [{title: 商品序号,k…...

统计的基本概念及抽样分布

文章目录 &#x1f34b;引言&#x1f34b;总体&#xff08;Population&#xff09;&#x1f34b;总体参数 &#x1f34b;样本&#xff08;Sample&#xff09;&#x1f34b;随机样本&#x1f34b;样本统计量 &#x1f34b;统计量&#xff08;Statistic&#xff09;&#x1f34b;…...

【C++】class的设计与使用(四)this指针

this指针 this作用域是在类内部&#xff0c;只能在成员函数中使用&#xff1b;this在成员函数的开始前构造&#xff0c;在成员函数的结束后清除&#xff1b;编译器在编译的时候也会自动加上this&#xff0c;它作为非静态成员函数的隐含形参&#xff0c;对各成员的访问均通过th…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...

嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)

目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 ​编辑​编辑 UDP的特征 socke函数 bind函数 recvfrom函数&#xff08;接收函数&#xff09; sendto函数&#xff08;发送函数&#xff09; 五、网络编程之 UDP 用…...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...