动态代理--通俗易懂

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

例子

梳理

  • 代理对象(接口):要包含被代理的对象的方法 ---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{
    @Override
    public 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);
    }
​
    @Override
    public void deleteUser() throws Exception {
        System.out.println("删除了10个用户");
        Thread.sleep(1000);
​
    }
​
    @Override
    public 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() {
            @Override
            public 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
[张三, 李四]

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

yolov5实例分割跑通以及C#读取yolov5_Seg实例分割转换onnx进行检测部署

一、首先需要训练yolov5_seg的模型&#xff0c;可以去网上学习&#xff0c;或者你直接用我的&#xff0c; 训练环境和yolov5—7.0的环境一样&#xff0c;你可以直接拷过来用。 yolov5_seg算法 链接&#xff1a;https://pan.baidu.com/s/1m-3lFWRHwg5t8MmIOKm4FA 提取码&…

Zombie Voices Audio Pack(僵尸游戏音频包)

僵尸声音音频包是600多个高质量声波的集合。 它提供了僵尸主题游戏所需的一切&#xff0c;这要归功于它的20多个类别&#xff1a; 攻击、咬、呼吸、窒息、损坏、死亡、进食、血腥、咕噜、大笑、疼痛、反应、尖叫、喉咙、呕吐、单词和句子。 我们的僵尸动画包带来的额外奖励&am…

自从棋牌游戏有了AI助阵,赢“麻”了!看这篇就够了

毛主席曾经说过&#xff1a;“中国对世界的三大贡献&#xff0c;第一是中医&#xff0c;第二是曹雪芹的《红楼梦》&#xff0c;第三是麻将牌。”麻将起源于中国&#xff0c;是国粹。各地的麻将玩法各不相同&#xff0c;比如云贵川地区的“缺一门”打法&#xff0c;广东麻将流行…

【课程设计】基于python的一款简单的计算器

我们是大二本科生团队&#xff0c;主力两人耗时3天完成了这款计算器的制作。希望大家给我们多多引流&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 欢迎各位优秀的高考学子报考长安大学&#xff0c;报考长安大学电子信息工程专业。 欢迎有志于就…

vite项目如何在本地启动https协议

vite项目如何在本地启动https协议 本地启动正常配置在vite.config.js文件中默认启动http协议的请求&#xff0c;如何改成https呢&#xff1f;今天的开发中遇到了这个问题项目需求&#xff1a; 本地启动https协议的前端页面并且正常访问后台https协议的接口 解决方法&#xff1a…

python学习-tuple及str

为什么需要元组 定义元组 元组的相关操作 元组的相关操作 - 注意事项 元组的特点 字符串 字符串的下标&#xff08;索引&#xff09; 同元组一样&#xff0c;字符串是一个&#xff1a;无法修改的数据容器。 如果必须要修改字符串&#xff0c;只能得到一个新的字符串&#xff…

如何对GD32 MCU进行加密?

GD32 MCU有哪些加密方法呢&#xff1f;大家在平时项目开发的过程中&#xff0c;最后都可能会面临如何对出厂产品的MCU代码进行加密&#xff0c;避免产品流向市场被别人读取复制。 下面为大家介绍GD32 MCU所支持的几种常用的加密方法&#xff1a; 首先GD32 MCU本身支持防硬开盖…

信息学一周赛事安排

本周比赛提醒 本周末有以下几场比赛即将开始&#xff1a; :::block-1 1.ABC-361 比赛时间&#xff1a;7月6日&#xff08;周六&#xff09;晚20:00 比赛链接&#xff1a;https://atcoder.jp/contests/abc361 3.CF-956(Div.2) 比赛时间&#xff1a;7月7日&#xff08;周日…

【日常记录】【JS】获取用户IP地址及其他信息

1. 查询本机的IP地址 1.1 通过命令提示符 电脑按下 ctrl r &#xff0c;输入 cmd 后按回车&#xff0c;打开命令提示符窗口输入命令&#xff1a; ipconfig &#xff0c;然后按回车 下面这个红色框里面就是 ip地址 在输出结果中找到“无线局域网适配器 WLAN”或“以太网适配器…

python-切片、集合

序列是指&#xff1a;内容连续、有序&#xff0c;可使用下标索引的一类数据容器 序列的常用操作 - 切片 切片的语法 序列的常用操作 - 切片 注意切片的范围是左闭右开 为什么使用集合 集合的常用操作 - 修改 集合的常用操作 - 集合长度 集合常用功能总结 集合的特点

python小练习04

三国演义词频统计与词云图绘制 import jieba import wordcloud def analysis():txt open("三国演义.txt",r,encodingutf-8).read()words jieba.lcut(txt)#精确模式counts {}for word in words:if len(word) 1:continueelif word "诸葛亮" or word &q…

一个使用 g++ 模块化编译的 hello world 示例( Ubuntu 20.04 )

1. 确认 ubuntu 版本&#xff1a; 2. 文件夹结构&#xff1a; 3. 各个文件内容&#xff1a; 3.1. myadd.cpp&#xff1a; #include<iostream> using namespace std; int add_xxx( int a,int b ){int result a b;cout << a << " " << …

责任大,权力小:项目经理如何有效管理项目

成为项目经理&#xff0c;我们才会发现这份工作远非想象中那般轻松。在大多数企业中&#xff0c;项目经理更像是小团队中的舵手&#xff0c;需要在有限的权力和资源下&#xff0c;承担起巨大的责任&#xff0c;甚至不惜牺牲个人时间&#xff0c;加班至深夜。责任重大而权力有限…

解析MySQL的数据类型:理解每种类型及其应用

MySQL是一种流行的关系型数据库管理系统&#xff0c;被广泛应用于Web应用开发中。在数据库设计的过程中&#xff0c;选择合适的数据类型至关重要&#xff0c;因为它不仅影响存储效率和数据完整性&#xff0c;还影响数据库操作的性能和查询速度。本文将详细介绍MySQL支持的各种数…

职业技能大赛引领下人工智能专业实训教学的改革研究

在新时代背景下&#xff0c;人工智能&#xff08;AI&#xff09;作为科技发展的前沿领域&#xff0c;正以前所未有的速度影响着社会经济的各个方面&#xff0c;对高素质应用型AI专业人才的需求日益迫切。职业技能大赛作为检验和提升学生实践能力的重要平台&#xff0c;对于促进…

linux内存屏障

why? 为什么要有内存屏障&#xff0c;内存屏障主要解决什么问题 What? 内存屏障都有哪些 How? 内存屏障如何使用 本篇文章主要解决前两个问题 一、为什么要有内存屏障 我们都知道计算机运算任务需要CPU和内存相互配合共同完成&#xff0c;其中CPU负责逻辑计算&#xf…

HUAWEI MPLS 静态配置和动态LDP配置

MPLS(Multi-Protocol Label Switching&#xff0c;多协议标签交换技术)技术的出现&#xff0c;极大地推动了互联网的发展和应用。例如&#xff1a;利用MPLS技术&#xff0c;可以有效而灵活地部署VPN(Virtual Private Network&#xff0c;虚拟专用网)&#xff0c;TE(Traffic Eng…

将iStoreOS部署到VMware ESXi变成路由器

正文共&#xff1a;888 字 19 图&#xff0c;预估阅读时间&#xff1a;1 分钟 前面把iStoreOS部署到了VMware workstation上&#xff08;将iStoreOS部署到VMware Workstation&#xff09;。如果想把iStoreOS直接部署到ESXi上&#xff0c;你会发现转换镜像不能直接生成OVF或者OV…

巴比达内网穿透:重塑企业级数据通信的高效与安全边界

在当今数据驱动的时代&#xff0c;企业对于高效、安全、低延迟的数据传输需求日益迫切。巴比达&#xff0c;作为企业级内网穿透领域的佼佼者&#xff0c;凭借其自主研发的第九代核心引擎——WanGooe Tunnel&#xff0c;为企业带来了前所未有的通信体验。通过一系列技术创新与优…

亚马逊云科技AWS免费大热AI应用开发证书(含题库、开卷)

亚马逊云科技AWS官方生成式AI免费证书来了&#xff01;内含免费AI基础课程&#xff01;快速掌握AWS的前沿AI技术&#xff0c;后端开发程序员也可以速成AI专家&#xff0c;了解当下最&#x1f525;的AWS AI架构解决方案&#xff01; 本证书内容包括AWS上的AI基础知识&#xff0c…