通俗易懂的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)-代理模式 的相关文章

  • Emacs 打字骨架对插入也许

    在 Eclipse 中 编辑 Java 代码时 如果我输入一个左括号 我会得到一对括号 如果我然后 输入 第二个括号 它不会插入额外的括号 我如何在 emacs 中得到它 Eclipse 编辑器足够聪明 当我输入闭括号时 它知道我刚刚完成了
  • 从插件设置 Maven 属性

    我在这里阅读了一些关于如何从 Maven 插件设置属性的问题 其中大多数讨论了应用程序的版本号 似乎没有简单的方法可以做到这一点 我发现的最佳解决方案是拥有一个从插件更新的 filter properties 文件 并由主 pom 文件使用
  • 匿名类*总是*维护对其封闭实例的引用吗?

    我正在处理一些代码 其中一个对象 foo 正在创建另一个对象 对象 bar 并将其传递给Callable 之后 foo 将返回 bar 然后我希望 foo 变得无法访问 即 可用于 垃圾收集 我最初的想法是创建Callable匿名 例如 c
  • 如何在异常处理程序中访问访问请求主体

    我们有一个 Spring Boot 应用程序 我们的控制器期望在我们的端点之一中有一个 XML 文档元素 PostMapping value api v1 do stuff consumes APPLICATION XML VALUE pr
  • Java 增强型 For-Loop 比传统的更快?

    所以我的理解是 增强的 for 循环应该更慢 因为它们必须使用迭代器 但是我的代码提供了混合结果 是的 我知道循环逻辑占用了循环中花费的大部分时间 对于少量迭代 100 1000 增强的 for 循环在使用和不使用 JIT 的情况下似乎都要
  • 使用 Bouncy Castle 重建 ED25519 按键 (Java)

    Bouncy Castle 的最新 测试版 版本 bcprov jdk15on 161b20 jar 支持 ED25519 和 ED448 EC 加密以进行签名 我设置了这个完整的工作示例 它按预期工作 我的问题 我是否正确重建了私钥和公钥
  • Java生成范围内不重复的随机数

    我想生成 1 到 4 范围内的随机数 包括 4 这是我的代码 int num r nextInt 4 1 r is instance of Random 但是 我在循环中运行上述代码 并且不想重复随机数 现在发生的事情我经常得到 1 1 1
  • 堆内存与对象内存

    根据一篇关于Java内存和特性的论文 内存分数分为两种类型 堆内存 即应用程序在运行时消耗的内存 对象内存 即程序中使用的各种对象分配的内存 例如整数和字符串等 他们的意思是stack当他们说时的记忆object记忆 或者它们是什么意思 很
  • IDEA:javac:源版本1.7需要目标版本1.7

    使用 IntelliJ IDEA 运行 JUnit 测试时 我得到 我该如何纠正这个问题 使用SDK 1 7 模块语言级别为1 7 Maven 构建工作正常 这就是为什么我相信IDEA配置问题 您很可能在此处从 Maven 导入了不正确的编
  • 在所有方法调用上允许类型见证有什么意义?

    假设我们有两种方法 如下所示 public static
  • 一起使用 String 和 int 时的 System.out.println 行为 [重复]

    这个问题在这里已经有答案了 考虑下面的代码片段 public class Student public static void main String args int a 3 int b 4 System out println a b
  • 字节流和字符流

    请解释一下什么是字节流和字符流 这些究竟意味着什么 Microsoft Word 文档是面向字节的还是面向字符的 Thanks 流是一种顺序访问文件的方式 字节流逐字节访问文件 字节流适用于任何类型的文件 但不太适合文本文件 例如 如果文件
  • 如何将空字符串序列化为单个空标签?

    我使用 Simple XML 框架序列化此类 Root public class HowToRenderEmptyTag Element required false private String nullString 我想得到
  • Hibernate SET 元素 order-by 子句

    我想知道 我可以平静地接受以下事实 当 fetch select 时 您可以在映射文件中的 SET 元素上设置 order by 属性 但如果您在创建查询时获取所有内容 这样安全吗 我的意思是 他们将结果放入 HashSet 中 我不认为这
  • 如何在 Struts 2 中访问 OGNL 跟踪评估?

    有人告诉我要优化网络应用程序 为此 我使用JProfiler https www ej technologies com products jprofiler overview html 我注意到很大一部分响应时间都花在了表示层上 特别是当
  • 如何使用JSqlParser向sql添加where条件?

    我想用JSqlParser向sql添加where条件 例如 Before select from test table where a 1 group by c After select from test table where a 1
  • 启动 Firefox 并等待其关闭

    Question 我想启动 Firefox 网络浏览器作为访问特定网站的过程 然后等到它关闭 一种特殊情况是浏览器可能已经打开并正在运行 因为用户可能已经访问过某个网站 在这种情况下 浏览器可能会在现有窗口中打开一个新选项卡 并且新启动的进
  • 无法验证 serde:org.openx.data.jsonserde.jsonserde

    我编写了这个查询来在配置单元上创建一个表 我的数据最初是 json 格式 所以我已经下载并构建了 serde 并添加了它运行所需的所有 jar 但我收到以下错误 FAILED Execution Error return code 1 fr
  • Java 8 流过滤器 - 基于排序的更新

    我正在尝试对过滤器中的字段进行排序 输入文件 样本记录 DocumentList Document id 5975ff00a213745b5e1a8ed9 u id mailboxcontent id 5975ff00a213745b5e1
  • 如何在Java中添加两个“卡”的值?

    我正在开发一个项目来模拟二十一点游戏中的第一笔交易 到目前为止 程序创建了两张随机等级 ACE 到 KING 和随机花色的牌 我正在努力创建一个切换表或 if else 梯形图 将两张卡的附加值分配为可变分数 下面的代码从概念上代表了我想要

随机推荐

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

    如果你是在建一栋房子 那么这个建造过程就会复杂得多 而糟糕的设计所引发的后果也更严重 首先你要决定准备建一个什么类型的房子 在软件开发里的类似事项称为问题定义 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 静态代理 何为静态 即在程序运行之前 代理