Spring 学习(六)代理模式

news2024/12/24 23:58:48

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();
          }
      }
      

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

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

相关文章

uniapp实现点击按钮分享给好友

<button class"share" open-type"share">分享</button>import {onLoad,onShareAppMessage,onShareTimeline} from dcloudio/uni-app onLoad(() > {//设置Menus菜单&#xff0c;使 发送给朋友/分享到朋友圈 两个按钮可以使用wx.showShareMen…

熟悉MySQL OCP和Oracle OCP和考试真实界面

解答OCP学员常问姚远老师的问题如下: 考试需要提前多久到达&#xff1f;&#xff08;提前15到30分钟到达&#xff09;考试需要带什么证件&#xff1f;&#xff08;考试必须携带2个证件&#xff1a;身份证另外一种证件。另外一种证件可以是&#xff1a;信用卡、护照、驾驶证、港…

【QT】QT事件Event大全

很高兴在雪易的CSDN遇见你 &#xff0c;给你糖糖 欢迎大家加入雪易社区-CSDN社区云 前言 本文分享QT中的事件Event技术&#xff0c;主要从QT事件流程和常用QT事件方法等方面展开&#xff0c;希望对各位小伙伴有所帮助&#xff01; 感谢各位小伙伴的点赞关注&#xff0c;小易…

解决cocoapods下载hermes太慢的问题

最近,在执行pod install命令安装iOS依赖包的时,运行到installing hermes engine 就直接卡住了。执行pod install --verbose 时,看到下载包的大小478M,但是下载速度高达 20kb/s。 对于这个问题,查阅了网上的一些资料,以下是一个可行的解决方案。 步骤1 打开node_modules…

11.2.0.4Oracle rac grid卸载安装注意事项

还有三天放国庆和中秋了&#xff0c;今天周一上班就跟丢了魂一样&#xff0c;本来两台11g RAC一个半小时搞定的事情&#xff0c;我从早上九点一直干到现在晚上八点半才干完&#xff0c;简直是昏了头了。安装的时候将大页设置错误&#xff0c;导致一套库直接系统崩了&#xff0c…

SpringBoot整合QQ邮箱发送验证码

1.项目介绍 基于SpringBoot QQ邮箱服务 Hutools实现的获取验证码功能&#xff0c;接下来从如何申请授权码&#xff0c;如何配置项目&#xff0c;如何启动项目&#xff0c;如何测试项目进行讲解&#xff0c;下面的图片是一个测试案例&#xff0c;使用postman进行测试&#xf…

[Qt]QListView 重绘实例之一:背景重绘

0 环境 Windows 11Qt 5.15.2 MinGW x64 1 系列文章 简介&#xff1a;本系列文章&#xff0c;是以纯代码方式实现 Qt 控件的重构&#xff0c;尽量不使用 Qss 方式。 《[Qt]QListView 重绘实例之一&#xff1a;背景重绘》 《[Qt]QListView 重绘实例之二&#xff1a;列表项覆…

多进程的实现原理-多道技术

前言&#xff1a; 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 操作系统 ​ 位于应用软件和硬件设备之间,本质是一个软件 核心作用: 为用户屏蔽了复杂繁琐的硬件接口;为应用程序提供了清晰易用的系统接口 …

Java --- MySQL8之索引优化与查询优化

目录 一、索引失效场景 1.1、全值匹配 1.2、最佳左前缀规则 1.3、主键插入顺序 1.4、计算、函数、类型转换(自动或手动)导致索引失效 1.5、类型转换导致索引失效 1.6、范围条件右边的列索引失效 1.7、不等于(! 或者<>)索引失效 1.8、is null可以使用索引&…

redis(2)-hiredis-centos-ubuntu 下安装和使用

ubuntu 下安装vsftpd sudo apt update sudo apt install vsfptd sudo systemctl status vsftpdvim /etc/vsftpd.conflocal_enablesYESwrite_enableYESanonymous_enableYESanon_mkdir_write_enableYES //允许匿名用户在FTP上创建目录anon_upload_enableYES //允许匿…

[每周一更]-(第64期):Dockerfile构造php定制化镜像

利用php官网镜像php:7.3-fpm&#xff0c;会存在部分插件缺失的情况&#xff0c;自行搭建可适用业务的镜像&#xff0c;才是真理 Dockerhub 上 PHP 官方基础镜像主要分为三个分支&#xff1a; cli: 没有开启 CGI 也就是说不能运行fpm。只可以运行命令行。fpm: 开启了CGI&#x…

2023.9.23 关于 HTTP 详解

目录 HTTP 协议 认识 URL HTTP 请求 认识方法 HTTP 响应 认识状态码 总结 HTTP 请求的构造 Form 表单构造 AJAX 构造 Postman 构造 HTTP 协议 应用层使用最广泛的协议浏览器 基于 HTTP协议 获取网站是 浏览器 和 服务器 之间的交互桥梁HTTP协议 基于传输层的 TCP协…

k8skubectl陈述式及声明式资源管理及金丝雀部署

文章目录 一.陈述式资源管理方法1.陈述式资源管理概念2.基本信息查看&#xff08;1&#xff09;查看版本信息&#xff08;2&#xff09;查看资源对象简写&#xff08;3&#xff09;查看集群信息&#xff08;4&#xff09;配置kubectl自动补全&#xff08;5&#xff09;node节点…

放弃webstrom转战vscode

本来是webstrom的忠实用户&#xff0c;无奈webstrom要么需要在网上找一个破解版或者不断的去找激活码&#xff0c;且破解版和激活码的文章总是很多&#xff0c;但是要找到真正有效的却总是要花费不少功夫。终于忍无可忍&#xff0c;转战vscode。&#xff08;注&#xff1a;文中…

MQTT上传图片数据的4G低功耗摄像头解决方案

为什么要使用MQTT上传数据图片呢&#xff1f; MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的&#xff0c;它工作在 TCP/IP协议族上&#xff0c;是为硬件性能低下的远程设备以及网络…

python使用蓝牙库选择

蓝牙库选择 pybluez 项目地址&#xff1a;https://github.com/pybluez/pybluez 文档地址&#xff1a;https://pybluez.readthedocs.io/en/latest/index.html 蓝牙支持&#xff1a;经典蓝牙 / BLE蓝牙【仅Linux】 平台支持&#xff1a; LinuxRaspberry PimacOSWindows✔️✔️…

本地搭建kafka并用java实现发送消费消息

1、下载kafka的jar包文件 https://www.apache.org/dyn/closer.cgi?path/kafka/3.1.0/kafka_2.12-3.1.0.tgz2、下载完成直接操作命令启动 1、打开新的terminal(终端)窗口&#xff0c;进入kafka的bin目录 启动zk./zookeeper-server-start.sh ../config/zookeeper.properties2、…

bash中执行比较的几种方法

bash 脚本中的 test 命令用于检查表达式的有效性&#xff0c;检查命令或表达式为 true 或者 false。此外&#xff0c;它还可以用于检查文件的类型和权限。 如果命令或表达式有效&#xff0c;则 test 命令返回0&#xff0c;否则返回1。 使用 test 命令 test 命令的基本语法如…

速卖通数据分析怎么看?速卖通数据分析工具有哪些?—站斧浏览器

速卖通数据分析怎么看&#xff1f; 1、关注销售指标&#xff1a;在进行速卖通数据分析时&#xff0c;卖家应特别关注销售指标&#xff0c;如销售额、订单量、转化率等。通过对这些指标的分析&#xff0c;卖家可以了解到自己店铺的销售状况以及变化趋势&#xff0c;进而采取相应…

【postgresql】 ERROR: multiple assignments to same column “XXX“

Cause: org.postgresql.util.PSQLException: ERROR: multiple assignments to same column "XXX"; bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: ERROR: multiple assignments to same column "XXX"; 原因&#xff1a;or…