JDK动态代理的原理解析、代码实现

news2024/10/7 16:26:22

代理就像是:买家(客户端)——销售(代理对象)——工厂(目标)

        买家不用直接去工厂买,而是直接通过销售就可以购买到,假设工厂生产的是杯子,那么工厂只需要提供杯子,而销售在不改变杯子的生产过程的情况下对杯子进行包装设计,广告宣传。提高其销量。

      代理模式中,代理对象充当了被代理对象的中间人,客户端通过代理对象来访问被代理对象,而不是直接访问被代理对象。主要目的是在不改变原始对象的情况下,提供额外的功能或控制访问。增强了代码的安全性、灵活性。

1、动态代理是什么?

      静态代理在编译时就已经确定代理类和被代理类的关系,代理类是手动编写的。在静态代理中,需要为每个被代理的类编写一个代理类。它需要手动编写代理类,当被代理的类较多时,会导致代码冗余。所以在这种情况下我们需要使用动态代理。

        动态代理在运行时动态生成代理类和代理对象,不需要手动编写代理类。在动态代理中,代理类是在运行时通过反射机制动态生成的。动态代理的优点是可以减少代码冗余,缺点是相对于静态代理,它的实现稍微复杂一些。

2、JDK动态代理的实现方式

        下面代码实例是通过调用经纪人代理对象调用明星的跳舞、rap方法。明星只负责工作,而在经纪人方法当中添加收钱的功能。

定义接口:我首先定义了一个Star接口,该接口有dance和rap两个接口:

public interface Star {

    /**
     * 跳舞
     */
    public void dance();

    /**
     * 说唱
     */
    public void rap();
}

创建Star接口实现类:在这个类当中将两个方法实现:

public class OnePeople implements Star{

    @Override
    public void dance() {
        System.out.println("我跳舞了");
    }

    @Override
    public void rap() {
        System.out.println("我唱了rap");
    }
}

创建InvocationHandler实现类

//当调用代理对象的方法时,实际上是调用了invoke()方法。在invoke()方法中,可以根据需要执行一些前置或后置操作,然后将方法调用转发给实际的对象。
public class MyInvocationHandler implements InvocationHandler {
    //被代理对象
    Object object;
    public MyInvocationHandler (Object o){
        object = o;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("我已经收好钱了,我的boss可以开始工作了");
        //通过反射调用被代理对象的方法。
        Object invoke = method.invoke(object, args);
        System.out.println("我们已经工作完毕,拍拍屁股离开");
        return invoke;
    }
}

创建代理对象:

public class Demo {
    public static void main(String[] args) {
        OnePeople onePeople = new OnePeople();
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(onePeople);
        //newProxyInstance()接受三个参数:类加载器、要实现的接口列表和一个InvocationHandler对象
        // 返回的是实现指定接口的代理类的实例。这个实例可以被强制转换为接口类型,以便在代码中使用。
        Star star = (Star) Proxy.newProxyInstance(onePeople.getClass().getClassLoader(),
                onePeople.getClass().getInterfaces(), myInvocationHandler);
        //调用跳舞方法
        star.dance();
        //调用rap方法
        star.rap();
    }
}

运行结果:

注意:JDK动态代理只能代理接口,不能代理具体的类。如果要代理具体的类,可以考虑使用其他的代理机制(CGLIB机制)。

3、动态代理的优点

  1. 灵活性:动态代理可以在运行时创建代理对象,而不需要在编译时就确定代理对象的类型。这使得动态代理更加灵活,可以根据需要动态地创建不同类型的代理对象。

  2. 可扩展性:动态代理可以通过实现InvocationHandler接口来自定义代理对象的行为。通过在InvocationHandler中编写自定义的逻辑,可以在代理对象的方法调用前后进行额外的操作,如日志记录、性能监控、事务管理等。这种可扩展性使得动态代理在很多场景下非常有用。

  3. 低耦合性:动态代理可以将代理对象的创建和代理逻辑的实现分离开来,从而实现低耦合性。代理对象的创建可以由代理工厂或者依赖注入容器等负责,而代理逻辑的实现可以由InvocationHandler来完成。这种低耦合性使得代码更加清晰、易于维护和扩展。

  4. 动态性:动态代理可以在运行时动态地修改代理对象的行为。这意味着可以根据需要动态地添加、修改或删除代理对象的方法,从而实现更加灵活的代理逻辑。

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

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

相关文章

C语言单链表OJ题(较难)

一、链表分割 牛客网链接 题目描述: 现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。 思路:…

idea如何开启远程调试

一:打包需要部署的jar包上传到服务器 二:服务器(开启远程调试接口) nohup java -jar -Xdebug -Xrunjdwp:transportdt_socket,servery,suspendn,address8453 xxx.jar > xxx.log 2>&1 & 三: idea配置rem…

【Linux】Linux下的一些系统文件详细介绍总结

一,~/.bashrc文件 简介 .bashrc 文件是 Linux 系统中的一个脚本文件,其主要作用是在用户登录 Shell 时自动执行一系列的命令和设置环境变量。它通常位于用户的家目录下,文件名为 ".bashrc",是每个用户都可以修改的个性化…

QtWebApp开发https服务器,完成客户端与服务器基于ssl的双向认证,纯代码操作

引言:所谓http协议,本质上也是基于TCP/IP上服务器与客户端请求和应答的标准,web开发中常用的http server有apache和nginx。Qt程序作为http client可以使用QNetworkAccessManager很方便的进行http相关的操作。Qt本身并没有http server相关的库…

2023年实验班招生考试题解

比赛连接:传送门 密码:2023qsb A.Zlzs problem(Easy Version) 题目描述: This is the easy version of this problem. The only difference between the easy and hard versions is the constraints on n and m. So I wont even take a g…

1、Spark SQL 概述

1、Spark SQL 概述 Spark SQL概念 Spark SQL is Apache Spark’s module for working with structured data. 它是spark中用于处理结构化数据的一个模块 Spark SQL历史 Hive是目前大数据领域,事实上的数据仓库标准。 Shark:shark底层使用spark的基于…

项目中使用git vscode GitHubDesktopSetup-x64

一、使用git bash 1.使用git bash拉取gitee项目 1.在本地新建一个文件夹(这个文件夹是用来存放从gitee上拉下来的项目的) 2.在这个文件夹右键选择 git bash here 3.输入命令 git init (创建/初始化一个新的仓库) 4.输入命令 git remote add origin …

opencv基础41-图像梯度-sobel算子详解cv2.Sobel()(边缘检测基础)

图像梯度是用于描述图像变化率的概念。在图像处理中,梯度指的是图像中每个像素的灰度值变化速率或方向。它常用于边缘检测和图像特征提取。 一维图像的梯度表示为函数 f(x) 的导数,而在二维图像中,梯度是一个向量,包含两个分量&am…

《HeadFirst设计模式(第二版)》第六章代码——命令模式

代码文件目录: Command package Chapter6_CommandPattern.Command;/*** Author 竹心* Date 2023/8/6**/public interface Command {public void execute();public void undo();//撤销该指令 }CeilingFan package Chapter6_CommandPattern.ElectricAppliance;/*** …

阿里云快速部署开发环境 (Apache + Mysql8.0+Redis7.0.x)

本文章的内容截取于云服务器管理控制台提供的安装步骤,再整合前人思路而成,文章末端会提供原文连接 ApacheMysql 8.0部署MySQL数据库(Linux)步骤一:安装MySQL步骤二:配置MySQL步骤三:远程访问My…

协议,序列化,反序列化,Json

文章目录 协议序列化和反序列化网络计算器protocol.hppServer.hppServer.ccClient.hppClient.cclog.txt通过结果再次理解通信过程 Json效果 协议 协议究竟是什么呢?首先得知道主机之间的网络通信交互的是什么数据,像平时使用聊天APP聊天可以清楚&#x…

【网络编程】利用套接字实现一个简单的网络通信(UDP实现聊天室 附上源码)

网络编程套接字 🐛预备知识🦋理解源IP地址和目的IP地址🐌认识端口号🐞 理解 "端口号" 和 "进程ID"🐜简单认识TCP协议🦟简单认识UDP协议🦗 什么是网络字节序 🕷相…

MySQL的关键指标及采集方法

MySQL 是个服务,所以我们可以借用 Google 四个黄金指标的思路来解决问题。 1、延迟 应用程序会向 MySQL 发起 SELECT、UPDATE 等操作,处理这些请求花费了多久,是非常关键的,甚至我们还想知道具体是哪个 SQL 最慢,这样…

【Linux】进程间通信——System V信号量

目录 写在前面的话 一些概念的理解 信号量的引入 信号量的概念及使用 写在前面的话 System V信号量是一种较低级的IPC机制,使用的时候需要手动进行操作和同步。在现代操作系统中,更常用的是POSIX信号量(通过sem_*系列的函数进行操作&…

linux系统虚拟主机开启支持Swoole Loader扩展

特别说明:只是安装支持Swoole扩展,主机并没有安装服务端。目前支持版本php5.4-php7.2。 1、登陆主机控制面板,找到【远程文件下载】这个功能。 2、远程下载文件填写http://download.myhostadmin.net/vps/SwooleLoader_linux.zip 下载保存的路…

SpringBoot 升级内嵌Tomcat

SpringBoot 更新 Tomcat 最近公司的一个老项目需要升级下Tomcat,由于这个项目我完全没有参与,所以一开始我以为是一个老的Tomcat项目,升级它的Tomcat依赖或者是Tomcat容器镜像,后面发现是一个SpringBoot项目,升级的是…

加速中产 “返贫” 的4个迹象

没有消息,就是好消息。这话放在现在的朋友圈子里,似乎很合适。最近接到两个朋友的电话,一个是朋友的诉苦电话,这位朋友曾是某大厂的高管,被裁后失业近1年,虽然当初赔了N1,但架不住这位朋友“房贷…

Maven 打包生成Windows和Liunx启动文件

新建一个springboot项目。 1、项目结构 2、pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocati…

ASP.NET Core MVC -- 将视图添加到 ASP.NET Core MVC 应用

Index页 右键单击“视图”文件夹&#xff0c;然后单击“添加”>>“新文件夹”&#xff0c;并将文件夹命名为“HelloWorld”。 右键单击“Views/HelloWorld”文件夹&#xff0c;然后单击“添加”>“新项”。 在“添加新项 - MvcMovie”对话框中&#xff1a; 在右上…

Misc取证学习

文章目录 Misc取证学习磁盘取证工具veracryto挂载fat文件DiskGenius 磁盘取证例题[RCTF2019]disk 磁盘[](https://ciphersaw.me/ctf-wiki/misc/disk-memory/introduction/#_2)内存取证工具volatility 内存取证例题数字取证赛题0x01.从内存中获取到用户admin的密码并且破解密码 …