通俗易懂的java设计模式(6)-代理模式

2023-10-26

1.什么是代理模式

为某个对象提供一个代理对象,通过这个代理对象,可以控制对原对象的访问。

通俗的解释:我们电脑桌面上的一个个快接方式,当我们点击这个快捷方式的时候,我们就间接地访问到了这个程序。

2.静态代理

何为静态?即在程序运行之前,代理类已经由程序员写好并生成.class文件了

下面是一个最最简单的例子,目的:使用鸡的代理对象,来帮我们创建鸡这个动物

2.1静态代理的简单代码实现

首先,创建一个接口,他代表所有的动物,规定了动物的所有行为

public interface Animal {
    void cry();
}

下面创建一个被代理对象的实体,这里以鸡为例

public class Chick implements Animal{
    private String name;

    public Chick(String name) {
        this.name = name;
        birth(name);
    }

    private void birth(String name) {
        System.out.println("名字是"+name+"的鸡出生了");
    }

    @Override
    public void cry() {
        System.out.println("我是一只叫"+name+"的鸡");
    }
}

下面是鸡这个动物的代理类,同样也要实现Animal接口

public class ProxyChick implements Animal{
    private String name;
    private Chick chick;

    public ProxyChick(String name) {
        this.name = name;
    }

    @Override
    public void cry() {
        if (chick==null){
            chick = new Chick(name);
        }
        chick.cry();
    }
}

测试使用鸡的代理类来获取鸡

public class ProxyTest {
    public static void main(String[] args){
        ProxyChick chick = new ProxyChick("蔡徐坤");
        chick.cry();
        System.out.println("================");
        chick.cry();
    }
}

在这里插入图片描述

2.2java中应用

spring的Aop

还记得面向面向切面编程吗?他又是如何实现对方法进行加强的呢?其实只要在代理对象调用被代理对象方法的前后加上要增强的内容即可。

我们可以在cry方法前后任意的位置去写我们增强的逻辑,下面就用两个print输出来模拟增强方法。

public class ProxyChick implements Animal{
    private String name;
    private Chick chick;

    public ProxyChick(String name) {
        this.name = name;
    }

    @Override
    public void cry() {
        if (chick==null){
            chick = new Chick(name);
        }
        //在方法之前增强
        System.out.println("一个真正的鳗");
        chick.cry();
        //在方法之后增强
        System.out.println("要学会唱跳rap打篮球");
    }
}

2.3静态代理的优缺点

  • 优点:
    • 使用代理模式,给程序带来了高扩展性
  • 缺点:
    • 为了实现代理模式,带来了额外的工作
    • 由于使用被代理对象之前需要经过代理对象,会增加时间开销
    • 使用静态代理,需要程序员编写大量的代理对象加大工作量

3.动态代理

核心:不用事先为想代理的类创建代理对象

代码实现重点:java.lang.reflect包下提供的Proxy类InvocationHandler接口

下面是简单的动态代理实现流程

3.1动态代理的简单代码实现

前几步和静态代理类似,首先,先创建一个接口,定义行为

public interface Animal {
    void cry();
}

创建接口的实现类,也就是被代理的类

public class Chick implements Animal{
    private String name;

    public Chick(String name) {
        this.name = name;
        birth(name);
    }

    private void birth(String name) {
        System.out.println("名字是"+name+"的鸡出生了");
    }

    @Override
    public void cry() {
        System.out.println("我是一只叫"+name+"的鸡");
    }
}

接下来,就是动态代理的具体实现,创建AnimalInvocationHandler类,他实现了InvocationHandler接口

动态代理流程解析:

1.AnimalInvocationHandler持有一个被代理对象

2.通过代理对象执行的方法,都会被替换成AnimalInvocationHandler中的invoke方法

3.代理对象会在invoke方法中,去执行被代理对象的方法,和invoke方法中其他代码语句

上述的三个步骤,其实就是Spring Aop的主要原理

public class AnimalInvocationHandler<T> implements InvocationHandler {
    //持有一个被代理的对象
    private T target;

    public AnimalInvocationHandler(T target) {
        this.target = target;
    }

    /**
     * 其中的三个参数
     * proxy:表示这个动态代理的对象
     * method:正在执行的方法
     * args:调用方法时传入的参数
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("正在代理执行"+proxy.getClass().getName()+"类的"+method.getName()+"方法");
        Object invoke = method.invoke(target, args);
        System.out.println("代理执行结束~");
        return invoke;
    }
}

测试

public class DynamicProxyTest {
    public static void main(String[] args) {
        //创建出被代理的对象
        Animal chick = new Chick("蔡徐坤");
        System.out.println("======================");
        //创建InvocationHandler,他和被代理对象是相关联的
        InvocationHandler chickHandler = new AnimalInvocationHandler<Animal>(chick);
        //得到代理对象,代理对象执行的每一个方法都会被刚刚InvocationHandler中的invoke方法代替
            Animal chickProxy = (Animal) Proxy.newProxyInstance(Animal.class.getClassLoader(),new Class<?>[]{Animal.class},chickHandler);

        chickProxy.cry();
    }
}

上面的代码解析:首先,chick对象是需要被代理的对象,我们把chick传给了chickHandler,并且,创建代理对象chickProxy时,chickHandler也是作为一个参数传入,最后,代理对象chickProxy中的方法在执行的时候,都被替换成了chickHandler中的invoke方法。

在这里插入图片描述

3.2动态代理的特点

  • 与静态代理不同,在上面的代码实现中,我们没有看到具体的代理类,动态代理中的被代理对象和代理对象,是通过InvocationHandler来完成代理的,所以就无须对每一个类都写一个代理类,只需要同一在invoke方法中修改即可。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通俗易懂的java设计模式(6)-代理模式 的相关文章

  • 获取对 JOptionPane 静态方法创建的对象的引用

    我想知道是否可以获取对由 JOptionPane 的静态方法之一 例如 showMessageDialog 创建的 JDialog 对象的引用 我打算修改对话框在屏幕上出现的位置 更具体地说 我希望对话框默认显示在主应用程序窗口的左上角 而
  • 在 JRE 级别限制密码套件

    我们的 Java 应用程序公开了许多不同的接口 SMTP FTP HTTP 并通过 SSL TLS 进行保护 现在的目标是限制这些接口上允许的密码套件仅包含 强 密码套件 我已经有了一个列表 并且很清楚如何使其适用于特定套接字 socket
  • 如何迭代 stringtemplate 中的 java 列表?

    我想迭代字符串模板内的休眠查询结果 我一直在寻找例子 但找不到任何东西 你能帮忙吗 谢谢 语法看起来像
  • 如何制作行业标准的桌面Java应用程序? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 给定“java.sql.SQLIntegrityConstraintViolationException”是否可以确定错误的列

    鉴于我有一个类型为 java sql SQLIntegrityConstraintViolationException 的异常 是否可以以编程方式确定错误的列 或多列 我问这个问题是因为我想将错误映射回客户端的数据模型以指示错误的字段 例如
  • java.lang.NoSuchMethodError: org.mockito.Mockito.framework()Lorg/mockito/MockitoFramework

    我一直面临一个特殊的问题 基本上 当我正常运行 Mockito 测试 即 作为 Junit 测试运行 时 它会出现以下错误 有人可以帮我看看我的错误是什么吗 收到的错误 java lang NoSuchMethodError org moc
  • 如何从另一个 Flux 中排除 Flux 中的所有元素

    我有两个Flux一个用于成功元素 另一个用于保存错误元素 Flux
  • Java中使用正则表达式确定字符串是否为URL [重复]

    这个问题在这里已经有答案了 可能的重复 检查字符串是否为有效 URL 的最佳正则表达式是什么 https stackoverflow com questions 161738 what is the best regular express
  • 在循环中使用 if 语句? - 加工

    假设我必须在 for 循环中使用 if 语句 并且 for 循环在特定条件下触发 而 if 语句仅在 for 循环达到特定阶段时触发 例如 条件是一个计数器 当发生特定事件 例如球从屏幕上掉下来 时 该计数器会进行计数 每次球穿过屏幕时 都
  • Java如何从字符串实例化一个类[重复]

    这个问题在这里已经有答案了 可能的重复 在 Java 中从变量创建新类 https stackoverflow com questions 1268817 create new class from a variable in java 我
  • Spring 应用程序启动前的 Spring Boot 设置日志记录

    我有一个项目 在启动 SpringApplication 之前需要日志记录机制 我怎样才能做到这一点 我尝试设置自己的日志记录机制 LogManager getLogManager readConfiguration 但在 Spring 应
  • 使用 iText 在内存上生成在磁盘上生成的 PDF

    我正在从 Java 应用程序生成 PDF 并且效果很好 问题是 PDF 在磁盘上生成为 Document documento new Document PageSize A4 25 25 25 25 PdfWriter writer Pdf
  • 此代码签名证书对于签名小程序有效吗?

    我们购买了代码签名证书来签名小程序 但在签名小程序时出现以下错误 C CM WEB INF gt jarsigner keystore code signing keystore C CM SweetApplet jar code sign
  • 使用pdfbox从pdf中提取图像

    我正在尝试使用 pdfbox 从 pdf 中提取图像 示例 pdfhere http www ignou ac in upload questionpaper CS 74 PDF 但我只得到空白图像 我正在尝试的代码 public stat
  • CellTables 和 css (GWT)

    有人可以帮我设置 CellTable 行的背景吗 拜托 我整晚都在努力做这件事 但一直失败 这是 让我发疯 我尝试过调用setRowStyles 但是那个 似乎不起作用 我读到你无法更改 设置样式后 CellTable 的样式 作为默认样式
  • Spring Boot 中的外部化配置,多个应用程序在同一容器中运行

    我正在构建多个 Spring Boot 应用程序 这些应用程序将部署在同一个 servlet 容器上 但我很难让 Spring Boot 按照我想要的方式使用外部化配置文件 而不是像框架想要的那样 情况 多个 Spring Boot 应用程
  • Java 有现成的时钟同步解决方案吗?

    我们有一个大型的高性能软件系统 它由多个交互的 Java 进程 不是 EJB 组成 每个进程可以在同一台机器上 也可以在不同的机器上 某些事件在一个进程中生成 然后以不同的方式传播到其他进程以进行进一步处理等 出于基准测试的目的 我们需要创
  • 在Android中创建自定义按钮类

    我正在尝试为我的 Android 应用程序创建自定义按钮类 public class TicTacButton extends Button 我已经在里面设置了所有构造函数TicTacButton并创建了自定义方法和属性 在我的主要活动中
  • 如何使用 Java 到 TestRail 的 API 将测试用例添加到现有测试运行中?

    我在执行期间创建了一个测试运行 我想在它们开始执行的同时添加测试用例 如果测试用例尚不存在 则已创建 并且该测试用例应该与其他测试用例一起添加到现有的测试运行中 我尝试过使用setCaseIds在运行期间和更新运行之后 但这会覆盖现有的运行
  • Jsplitpane 自动调整大小

    我有一个 JSPlitPane 它们之间有 50 的分隔线 这工作正常 但是 当我在右侧添加一些 JLabels 时 jsplitpane 会忽略我的 50 分隔符 左侧窗格会增加其大小 并会挤压右侧窗格 为什么会发生这种情况以及如何解决

随机推荐

  • 用房屋建筑方式理解软件构建

    如果你是在建一栋房子 那么这个建造过程就会复杂得多 而糟糕的设计所引发的后果也更严重 首先你要决定准备建一个什么类型的房子 在软件开发里的类似事项称为问题定义 problem definition 接下来 你必须和某个建筑师 archite
  • java代码规范(转载整合)

    1 标识符命名规范 1 1 概述 标识符的命名力求做到统一 达意和简洁 1 1 1 统一 统一是指 对于同一个概念 在程序中用同一种表示方法 比如对于供应商 既可以用supplier 也可以用provider 但是我们只能选定一个使用 至少
  • 数据库文件被.eight后缀勒索病毒加密?不要惊慌,91数据恢复专家教您应对处理!

    当企业遭受勒索病毒攻击时 数据库文件被加密 这会导致企业无法访问其重要的业务数据 会给企业带来较大的困扰 本篇文章 91数据恢复专家将会针对 tsai shen zohomail eu eight勒索病毒 介绍如何恢复被 tsai shen
  • keras部分介绍

    1 keras 关于batch normalization函数参数axis 3的解释 https www zhihu com question 318398221 tips BN层的作用 1 加速收敛 2 控制过拟合 可以少用或不用Drop
  • 2023年面试问答-二分查找

    正常实现 Input 1 2 3 4 5 key 3 return the index 2 public int binarySearch int nums int key int l 0 h nums length 1 while l l
  • 一键端2

    新仙剑ol 链接 http pan baidu com s 1i3xZHLb 密码 hyly 链接 http pan baidu com s 1c0HgGKw 密码 druj 本帖隐藏的内容 龙之谷133服务端 链接 http pan ba
  • 索琦c语言程序设计第二版第七章,C语言程序设计自学考试大纲(2000年7月版).doc...

    天津市高等教育自学考试课程考试大纲 课程名称 应用程序基础及设计 课程代码 1115 4874 第一部分 课程性质与设置目的 一 课程性质与特点 应用程序基础及设计 课程是高等教育自学考试电子信息工程专业的必修课 是该专业一门重要的基础课
  • Qt实现TCP客户端和服务器通讯程序

    复习的心态过一遍之前基础的一些东西 Qt封装了QTcpServer和QTcpSocket两个类 其中QTcpServer继承自QObject 通过listen 函数监听传入的客户端连接 当Client连接上时 QTcpServer会发出ne
  • 使 QComboBox 下拉一个带复选框的树形列表

    背景 在项目开发过程中需要使 QComboBox 下拉一个树形列表 直接通过 setModel 和 setView 设置 combox 控件可以实现 但是在单击节点箭头按钮时也会隐藏下拉框的显示 因此需要重新实现 QComboBox 的方法
  • 解决vue 路由传参 页面刷新或者后退参数丢失的问题

    vue路由传递参数如果用params传递参数 那么页面刷新就会丢失数据 可以改用query来传递参数 这样刷新就不会丢失 this router push path business bizInspectionTaskSub query f
  • Db2 v11.1 Upgrade to V11.5 HADR 模式

    https www ibm com docs en db2 11 5 topic methods universal versus product specific fix packs Universal versus product sp
  • RocketMQ重置消费位点源码分析

    这里是weihubeats 觉得文章不错可以关注公众号小奏技术 文章首发 拒绝营销号 拒绝标题党 背景 最近在使用RocketMQ的重置消费位点的时候经常出现报错 所以就打算研究下RocketMQ是如何重置消费者的消费位点的 RocketM
  • 图像形态学处理(膨胀腐蚀开闭运算)——数字图像处理学习八(C++版)

    一 基本概念 1 形态学的基本思想是利用一种特殊的结构元来测量或提取输入图像中相应的形状或特征 以便进一步进行图像分析和目标识别 2 图像的形态学处理是对二值图像进行处理 所以在形态学处理前需要将图像二值化 3 结构元可以是任意形状 结构元
  • 可信执行环境(TEE)技术介绍(Trusted Execution Environment)

    本文对当前流行的移动终端TEE技术做简要概述 并对一些细节展开讨论 1 当前移动安全背景 当前移动终端面临这严重的安全威胁 威胁点如下图所示 因此移动厂商 用户 服务提供商等各方都对移动安全提出了强烈的需求 2 REE介绍 Rich Exe
  • 线程安全

    线程安全 多线程的执行顺序不可重现 但是必须要求执行结果必须可以重现 线程的共享数据操作不完整性就一定会出现数据被破坏 而导致结果无法预知的问题 线程的安全问题 同步处理的引入 在java语言中存在两种内建的synchronized语法 s
  • ng-model

    ng model指令用来将input select text area或自定义表单控件同包含它们的作用域中的属性进行绑定 它可以提供并处理表单验证功能 在元素上设置相关的CSS类 ng valid ng invalid等 并负责在父表单中注
  • 【解决】2021-07-30Caused by: com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException:

    Caused by org springframework beans factory BeanCreationException Error creating bean with name sqlTemplate defined in U
  • python实现向图像随机添加高斯白噪声,并修改尺寸

    基于python向图像随机添加高斯噪声 并修改尺寸 噪声分布设置为 均值为0 方差分布在0 50之间 coding utf 8 Created on Nov Mon 29 14 09 45 2021 author 瀛台夜雪 import o
  • 【opencv】基于opencv实现人脸识别,从环境搭建到代码实现(超详细教程)

    前言 目标 让计算机通过训练做到认识我或者检测出视频中的人是谁 本文是一个学习笔记 记录一下自己的实现过程 在实现过程中遇到的问题以及个人对知识的理解 一 环境配置 1 软件安装 首先先安装一下必须的软件 python pycharm op
  • 通俗易懂的java设计模式(6)-代理模式

    1 什么是代理模式 为某个对象提供一个代理对象 通过这个代理对象 可以控制对原对象的访问 通俗的解释 我们电脑桌面上的一个个快接方式 当我们点击这个快捷方式的时候 我们就间接地访问到了这个程序 2 静态代理 何为静态 即在程序运行之前 代理