动态代理(通俗易懂)

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

例子

梳理

  • 代理对象(接口):要包含被代理的对象的方法 ---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,一经查实,立即删除!

相关文章

罗克韦尔 AB 1756-OA16控制器 模块 处理器

罗克韦尔 AB 1756-OA16该模块是任何自动化系统的重要组成部分&#xff0c;提供对各种过程的精确控制。它被设计为易于安装和使用&#xff0c;具有用户友好的界面&#xff0c;允许简单的配置和监控。 罗克韦尔 AB 1756-OA16控制器是一款为工业应用而设计的先进控制系统。它具有…

React快速入门-跟着AI学习react

React的快速入门可以遵循以下步骤进行&#xff0c;我将结合参考文章中的相关信息&#xff0c;以分点表示和归纳的形式给出详细步骤&#xff1a; 一、React基础知识了解 React的概念和特点&#xff1a; React是一个专注于构建用户界面的JavaScript库&#xff0c;采用声明式设计…

python将多个文件夹里面的文件拷贝到一个文件夹中

网上可以搜到很多方式&#xff0c;有的好使&#xff0c;有的不好使&#xff0c;亲测如下脚本可用&#xff0c;并可达到我想要的效果&#xff0c;只将多个文件夹里的文件拷贝到一个文件夹中&#xff0c;不拷贝文件夹本身&#xff0c;如果需要文件夹也拷贝打开注释行即可 import…

初次使用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…

记录一次解决循环依赖

场景 写权限模块-登录验证这一块的时候&#xff0c;遇到了一个比较有意思的问题&#xff0c;循环依赖: The dependencies of some of the beans in the application context form a cycle:userController defined in file xxx↓userServiceImpl defined in file xxxx ┌───…

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

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

TortoiseSVN 使用教程

TortoiseSVN 使用教程 1. 引言 TortoiseSVN 是一个开源的版本控制系统,它基于 Subversion(SVN)系统,为 Windows 操作系统提供了一套方便的图形用户界面。通过 TortoiseSVN,用户可以轻松地管理文件的版本,进行团队协作,以及跟踪文件的变更历史。本教程将详细介绍 Torto…

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

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

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

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

【代码随想录_Day24】134. 加油站 135. 分发糖果 860. 柠檬水找零 406. 根据身高重建队列

Day24 OK&#xff0c;今日份的打卡&#xff01;第二十四天 以下是今日份的总结加油站分发糖果柠檬水找零根据身高重建队列 以下是今日份的总结 加油站分发糖果柠檬水找零根据身高重建队列 今天的题目难度不低&#xff0c;而且非常的有意思&#xff0c;尽量还是写一些简洁代码…

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

继续花键的话题&#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;在网上找了一些办法&…