动态代理(通俗易懂)

程序为什么需要代理?代理长什么样?

例子

梳理

  • 代理对象(接口):要包含被代理的对象的方法 ---Star

  • 被代理对象:要实现代理对象(接口) ---SuperStar

  • 代理工具类:创建一个代理,返回值用代理对象,参数传被代理的对象,用Proxy代理类new一个实例,并重写invoke方法 --- 就是代理对象要做的事情

实体类,被代理的对象

(要实现代理)


package com.dev.springBootDemo.proxy;/*** @author zhumq* @date 2024/7/2 20:51*/
public class SuperStar implements Star{private String name;public SuperStar(String name) {this.name = name;}public String sing(String singName) {System.out.println(this.name + "正在唱:" + singName);return "唱完了!谢谢大家!";}public void dance() {System.out.println(this.name + "正在跳舞中~~~" );}}
 

代理对象(接口)

要包含被代理的对象的方法

package com.dev.springBootDemo.proxy;/*** @author zhumq* @date 2024/7/2 20:56*/
public interface Star {void dance();String sing(String singName);
}

代理工具类 :

创建一个代理,返回值用代理对象,参数传被代理的对象,用Proxy代理类new一个实例,并重写invoke方法 --- 就是代理对象要做的事情

package com.dev.springBootDemo.proxy;
​
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
​
/*** @author zhumq* @date 2024/7/2 20:57*/
public class ProxyUtil {public static Star createProxy(SuperStar superStar) {/*** (lassLoader loader , Class<?>[] interfaces, InvocationHandler h )* 参数1:用于指定一个类加载器* 参数2:用于指定一个接口数组,因为一个代理类可以代理多个接口,所以可以指定多个接口*       也就是指定生成的代理长什么样* 参数3:用于指定一个InvocationHandler对象,当调用代理类的方法时,就会自动调用InvocationHandler中的invoke方法*       (指定InvocationHandler中的invoke方法,在调用Star接口中的方法时,就会自动执行)*       也就是生成的代理对象要做什么}*/Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), new Class[]{Star.class}, new InvocationHandler() {@Override // 回调方法public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 代理对象要做的事情// 唱歌要先租场地,跳舞要去请老师教if ("sing".equals(method.getName())) {System.out.println("代理要去做:唱歌要先租场地");} else if ("dance".equals(method.getName())) {System.out.println("代理要去做:跳舞要去请老师教");}return method.invoke(superStar, args);}});return starProxy;}
}
​

测试类:

package com.dev.springBootDemo.proxy;
​
/*** @author zhumq* @date 2024/7/2 21:16*/
public class TestProxy {public static void main(String[] args) {SuperStar superStar = new SuperStar("周杰伦");Star proxy = ProxyUtil.createProxy(superStar);System.out.println(proxy.sing("稻香"));proxy.dance();}
}

输出

代理要去做:唱歌要先租场地
周杰伦正在唱:稻香
唱完了!谢谢大家!
代理要去做:跳舞要去请老师教
周杰伦正在跳舞中~~~

解决实际问题

  • UserService

  • UserServiceImpl

  • ProxyUtil

  • TestProxy

UserService

package com.dev.springBootDemo.proxy2;/*** 用户业务接口* @author zhumq* @date 2024/7/2 21:33*/
public interface UserService {// 登录功能void login(String loginName, String password) throws Exception;// 删除用户功能void deleteUser() throws Exception;// 查询用户功能String[] selectUsers() throws Exception;
}

UserServiceImpl

package com.dev.springBootDemo.proxy2;
​
/*** 用户业务实现(面向接口编程鸟纲)* @author zhumq* @date 2024/7/2 21:35*/
public class UserServiceImpl implements UserService{@Overridepublic void login(String loginName, String password) throws Exception {
​if ("admin".equals(loginName) && "123456".equals(password)) {System.out.println("登录成功");}else {System.out.println("登录失败");}Thread.sleep(1000);}
​@Overridepublic void deleteUser() throws Exception {System.out.println("删除了10个用户");Thread.sleep(1000);
​}
​@Overridepublic String[] selectUsers() throws Exception {System.out.println("查询了2个用户");String[] users = new String[]{"张三", "李四"};Thread.sleep(1000);return users;}
}

ProxyUtil

package com.dev.springBootDemo.proxy2;
​
import com.dev.springBootDemo.proxy.Star;
​
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
​
/*** @author zhumq* @date 2024/7/2 21:41*/
public class ProxyUtil {// 为用户业务对象创建代理public static UserService createProxy(UserService userService) {UserService userServiceProxy = (UserService) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), new Class[]{UserService.class}, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if ("login".equals(method.getName()) || "deleteUser".equals(method.getName())|| "selectUsers".equals(method.getName())) {
​long startTime = System.currentTimeMillis();
​Object s = method.invoke(userService, args);
​long endTime = System.currentTimeMillis();
​System.out.println(method.getName() + "方法耗时:" + (endTime - startTime) / 1000 + "s");
​return s;} else {return method.invoke(userService, args);}}});return userServiceProxy;}
}

TestProxy

package com.dev.springBootDemo.proxy2;
​
import java.util.Arrays;
​
/*** @author zhumq* @date 2024/7/2 21:49*/
public class TestProxy {public static void main(String[] args) throws Exception {UserService userService = ProxyUtil.createProxy(new UserServiceImpl());
​System.out.println("----------------用户登录-------------------");userService.login("admin", "123456");System.out.println("----------------用户删除-------------------");userService.deleteUser();System.out.println("----------------用户查询-------------------");String[] users = userService.selectUsers();System.out.println(Arrays.toString(users));}
}

输出:

----------------用户登录-------------------
登录成功
login方法耗时:1s
----------------用户删除-------------------
删除了10个用户
deleteUser方法耗时:1s
----------------用户查询-------------------
查询了2个用户
selectUsers方法耗时:1s
[张三, 李四]

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

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

相关文章

初次使用GitHub教程入门

注册一个github账户 访问地址&#xff1a;https://github.com/&#xff0c;点击右上角sign up&#xff0c;录入以下信息&#xff0c;邮箱&#xff0c;密码&#xff0c;账号&#xff0c;会有邮箱验证&#xff0c;跟着步骤来就好了 配置 本机上设置你的github的邮箱和用户名 …

51-5 权限维持2 - 影子账号(隐藏用户)

权限维持技术 权限维持技术(Persistence,也称为权限持久化)是一种能够在系统重启、用户更改密码或其他可能导致访问中断的情况下保持对系统访问的技术。例如,它包括创建系统服务、利用计划任务、修改系统启动项或注册表、以及映像劫持等方法。 创建影子账户 影子账户是指隐…

【管理咨询宝藏139】某大型快消集团公司多渠道销售管理体系方案

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏139】某大型快消集团公司多渠道销售管理体系方案 【格式】PDF版本 【关键词】罗兰贝格、营销咨询、战略规划 【核心观点】 - 销售体系建设主要需…

谷粒商城学习-06-使用vagrant快速创建linux虚拟机

这一节的内容是在Windows上安装虚拟机。 为什么要按照虚拟机呢&#xff1f; 原因是很多软件只能在Linux下运行&#xff0c;有的虽然也可以在Windows上运行&#xff0c;但从安装到运行会遇到很多问题&#xff0c;为这些解决这些问题花时间对于大多数人特别是初学者是没有什么价…

数字人直播源码开发全攻略揭秘:如何搭建自己的数字人直播平台?

当前&#xff0c;数字人直播逐渐成为众多中小型企业线上带货和品牌宣传的不二之选&#xff0c;而艾媒研究数据也显示&#xff0c;超五成以上的被调查群体的企业使用过虚拟人技术&#xff0c;超三成被调查群体的企业计划使用虚拟人技术。在此背景下&#xff0c;越来越多的创业者…

android应用的持续构建CI(一)-- 总体设计

一、背景 接下里我希望通过一系列的文章&#xff0c;把android应用的构建梳理一遍&#xff0c;从总体设计到逐个环节的实现。 总体设计jenkins集成手动签名依赖环境应用管理 二、构建流程图 三、技术组件 jenkinsjdkgradle360加固 既然是android应用的持续构建&#xff0c…

Web3 开发者入门手册:技能、工具和职业前景

原文&#xff1a;https://remote3.co/blog-post/how-to-become-a-web3-developer 作者&#xff1a;Paul Anderson 编译&#xff1a;TinTinLand Web3 是 2024 年科技领域最受瞩目的话题之一——Web3 令人激动的实用潜力可以跨越多个行业&#xff0c;早期采用者更有机会在未来…

亚马逊云服务器的价格真的那么贵吗?一年要花多少钱?

亚马逊Web服务&#xff08;AWS&#xff09;作为全球领先的云计算平台&#xff0c;其定价策略常常引起用户的关注。很多人可能会问&#xff1a;"AWS真的那么贵吗&#xff1f;"实际上&#xff0c;这个问题的答案并不是简单的"是"或"否"&#xff0c…

【大数据综合试验区1008】揭秘企业数字化转型:大数据试验区政策数据集大公开!

今天给大家分享的是国内顶级期刊中国工业经济2023年发布的最新期刊《政策赋能、数字生态与企业数字化转型——基于国家大数据综合试验区的准自然实验》文章中所使用到的数据集——国家大数据综合试验区政策数据集以及工具变量数据&#xff0c;该文章基于2009-2019年中国上市企业…

花键参数确定的流程是怎么样的?

继续花键的话题&#xff0c;今天跟小伙伴们一同学习一下&#xff1a;渐开线花键的参数确定的一般流程及基本方法。 前面有好几篇介绍了花键的基本参数的概念&#xff0c;包括规格、模数、齿数、压力角等等。以及花键的定心方式&#xff0c;内外花键的配合方式。那么这些参数的…

ARM架构 AArch64 基础知识介绍

介绍 aarch64是 ARM 架构的 64 位版本&#xff0c;它是 ARMv8 架构的一部分&#xff0c;被设计用来提供更高的性能和更大的地址空间&#xff0c;同时保持与 32 位 ARM 架构的兼容性。AArch64 是 ARMv8 的 64 位指令集架构&#xff08;ISA&#xff09;&#xff0c;它提供了丰富的…

2023 最新版IntelliJ IDEA 2023.1创建Java Web前(vue3)后端(spring-boot3)分离 项目详细步骤(图文详解)

文章目录 &#x1f6a9; 接上篇&#x1f3f3;‍&#x1f308; 项目构建所需的相关工具JavaIDEAmavenNodeJSVueVisual Studio Code &#x1f30c; 后端项目创建详细步骤&#x1f6eb; 1、开始创建新项目&#x1f6eb; 2、输入项目名称、选择项目存储位置、项目管理工具&#xff…

昇思25天学习打卡营第4天|yulang

今天主要了解了数据集 Dataset&#xff0c;主要包含了&#xff1a;数据集加载、数据集迭代、数据集常用操作、 可随机访问数据集、可迭代数据集、生成器。对于生成器很好理解&#xff0c;用代码来造数据&#xff0c;可以动态地生成数据。主要作用数据集通常被用于训练模型

tampermonkey插件下载国家标准文件

#创作灵感# 最近在一个系统招标正文中看到了一些国家标准&#xff0c;想要把文章下载下来&#xff0c;方便查阅&#xff0c;但是“国家标准全文公开系统”网站只提供了在线预览功能&#xff0c;没有提供下载功能&#xff0c;但是公司又需要文件&#xff0c;在网上找了一些办法&…

gin项目部署到服务器并后台启动

文章目录 一、安装go语言环境的方式1.下载go安装包&#xff0c;解压&#xff0c;配置环境变量2.压缩项目上传到服务器并解压3.来到项目的根目录3.开放端口&#xff0c;运行项目 二、打包的方式1.在项目的根目录下输入以下命令2.把打包好的文件上传到服务器3.部署网站4.ssl证书 …

C++字体库开发之字体回退三

代码片段 class FontCoverage { public: using SP std::shared_ptr<FontCoverage>; virtual ~FontCoverage() default; virtual void set(int index, FontTypes::CoverageLevel level) 0; virtual FontTypes::Coverag…

004 线程的状态

文章目录 Java线程可能的状态&#xff1a; 状态名称说明NEW初始状态&#xff0c;线程被构建&#xff0c;但是还没有调用start()方法RUNNABLE运行状态&#xff0c;Java线程将操作系统中的就绪和运行两种状态笼统地称作"运行中"BLOCKED阻塞状态&#xff0c;表示线程阻…

职场办公受欢迎的电脑桌面便签,手机电脑同步的备忘录

在快节奏的职场生活中&#xff0c;有效的时间管理和信息记录变得尤为重要。为了帮助大家更好地应对工作挑战&#xff0c;好用的电脑桌面便签和手机电脑同步的备忘录&#xff0c;好用便签应运而生&#xff0c;成为了当前职场办公中的得力助手。 好用便签是一款备受青睐的电脑桌…

阿里云物联网应用层开发:第三部分,微信小程序和web客户端实现

文章目录 哔哩哔哩视频教程1、阿里云物联网平台对接微信小程序2、阿里云物联网平台对接web客户端2-1MQTT服务器编写2-2 web端Servlet部分编写备注哔哩哔哩视频教程 【阿里云物联网综合开发,STM32+ESP8266+微信小程序+web客户端一篇教程详细讲解】 https://www.bilibili.com/v…

.NET下的开源OCR项目:解锁图片文字识别的新篇章

在数字化时代&#xff0c;从图片中高效准确地提取文字信息已成为众多应用场景的迫切需求。OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09;技术正是满足这一需求的关键技术。对于.NET开发者而言&#xff0c;幸运的是&#xff0c;存在多个开…