当前位置: 首页 > news >正文

设计模式8:代理模式-动态代理

上一篇:设计模式8:代理模式-静态代理

目录

  • 如何理解“动态”这两个字?
  • 动态代理简单的代码实例
  • 一个InvocationHandler代理多个接口
  • 有动态代理,为什么还要用Cglib代理?

如何理解“动态”这两个字?

“动态”的含义是代码生成代理类,一个代理类可以代理多个接口

动态区别于死板,静态代理中一个代理类只能代理一个接口,其他不同的接口,就需要再手写不同的代理类,这就很死板

动态代理类似于在安卓里面,我们常说的动态申请权限,其实就是用java或kotlin代码申请权限,而不是在AndroidManifest.xml文件里面写死一次可以申请一个或多个权限

上一篇:中,StationProxyStarProxy都是我们手写的代理类。动态代理可以自动生成代理类。

动态代理简单的代码实例

动态代理需要jdk中提供的两个类InvocationHandlerProxy,重写InvocationHandler接口实现代理方法,Proxy负责生成代理对象。
上篇文章中“明星代理”的例子,用动态代理实现如下:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;interface IStar {void sing(double money);
}class StarImpl implements IStar {public void sing(double money) {System.out.println("唱歌,收入" + money + "元");}
}class MyInvocationHandler implements InvocationHandler {private Object target;public MyInvocationHandler(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("请先预约时间");System.out.println("沟通出场费用");double money= (double) args[0];if (money < 100000) {System.out.println("对不起,出场费10w万以内不受理");return null;}System.out.println("经纪人抽取了"+ money * 0.2 + "代理费用");args[0] = money * 0.8;Object result = method.invoke(target, args);System.out.println("演唱完毕");return result;}
}public class DynamicProxyExample {public static void main(String[] args) {//原始对象IStar mStar = new StarImpl();InvocationHandler handler = new MyInvocationHandler(mStar);//代理对象IStar proxyHello = (IStar) Proxy.newProxyInstance(mStar.getClass().getClassLoader(),mStar.getClass().getInterfaces(),handler);proxyHello.sing(200000);}
}

运行结果:

请先预约时间
沟通出场费用
经纪人抽取了40000.0代理费用
唱歌,收入160000.0元
演唱完毕

一个InvocationHandler代理多个接口

动态代理的核心优势就在于,一个代理类,可以代理多个接口。如下,演示的是一个代理handler,同时代理两个接口InterfaceA和InterfaceB:

package dynamic_proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;interface InterfaceA {void methodA();
}interface InterfaceB {void methodB();
}class ClassA implements InterfaceA {public void methodA() {System.out.println("执行methodA");}
}class ClassB implements InterfaceB {public void methodB() {System.out.println("执行methodB");}
}class MyInvocationHandler implements InvocationHandler {private Object target;public MyInvocationHandler(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (method.getName().equals("methodA")) {System.out.println("调用methodA之前");Object result = method.invoke(target, args);System.out.println("调用methodA之后");return result;} else if (method.getName().equals("methodB")) {System.out.println("调用methodB之前");Object result = method.invoke(target, args);System.out.println("调用methodB之后");return result;} else {throw new UnsupportedOperationException("Unsupported method: " + method.getName());}}
}public class DynamicProxyExample {public static void main(String[] args) {InvocationHandler handlerA = new MyInvocationHandler(new ClassA());InterfaceA proxyA = (InterfaceA) Proxy.newProxyInstance(handlerA.getClass().getClassLoader(),new Class[]{InterfaceA.class},handlerA);proxyA.methodA();InvocationHandler handlerB = new MyInvocationHandler(new ClassB());InterfaceB proxyB = (InterfaceB) Proxy.newProxyInstance(handlerB.getClass().getClassLoader(),new Class[]{InterfaceB.class},handlerB);proxyB.methodB();}
}

代码执行结果:

调用methodA之前
执行methodA
调用methodA之后
调用methodB之前
执行methodB
调用methodB之后

动态代理大揭秘,带你彻底弄清楚动态代理!

有动态代理,为什么还要用Cglib代理?

动态代理只能把代理对象,赋值给接口,如上面的例子。不能把代理对象直接赋值一个普通类。而Cglib代理可以做到。具体怎么做的,下篇文章再讲。

相关文章:

设计模式8:代理模式-动态代理

上一篇&#xff1a;设计模式8&#xff1a;代理模式-静态代理 目录 如何理解“动态”这两个字&#xff1f;动态代理简单的代码实例一个InvocationHandler代理多个接口有动态代理&#xff0c;为什么还要用Cglib代理&#xff1f; 如何理解“动态”这两个字&#xff1f; “动态”…...

tcp字节传输(java)-自定义包头和数据识别

1、背景 tcp传输的时候会自动拆包&#xff0c;因此服务端接收的数据段可能跟客户端发送过来的数据段长度不一致&#xff0c;比如客户端一次发送10000个字节。但是服务端接收了两次才接收完整&#xff08;例如第一次接收6000字节&#xff0c;第二次接收4000字节&#xff09;。但…...

pyspark 系统找不到指定的路径; \Java\jdk1.8.0_172\bin\java

使用用具PyCharm 2023.2.1 1&#xff1a;pyspark 系统找不到指定的路径&#xff0c; Java not found and JAVA_HOME environment variable is not set. Install Java and set JAVA_HOME to point to the Java installation directory. 解决方法&#xff1a;配置正确环境变量…...

UE4 Physics Constraint Actor 实现钟摆效果

放入场景&#xff0c;然后将一个球体放入场景 选择小球 将小球改为Movable 选择模拟物理&#xff0c;并将小球移除平衡点 就实现了...

UE4/UE5 动画控制

工程下载​ ​​​​​​​​​​​​​https://mbd.pub/o/bread/ZJ2cm5pu 蓝图控制sequence播放/倒播动画&#xff1a; 设置开启鼠标指针&#xff0c;开启鼠标事件 在场景中进行过场动画制作 设置控制事件...

Springboot整合shiro

导入依赖 <!-- 引入springboot的web项目的依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency> ​ <!-- shiro --><depende…...

阻塞/非阻塞、同步/异步(网络IO)

1.阻塞/非阻塞、同步/异步(网络IO) 【思考】典型的一次 IO 的两个阶段是什么&#xff1f; 数据就绪 和 数据读写 数据就绪 &#xff1a;根据系统 IO 操作的就绪状态 阻塞 非阻塞 数据读写 &#xff1a;根据应用程序和内核的交互方式 同步 异步 陈硕&#xff1a;在处理 IO …...

为什么大家会觉得考PMP没用?

一是在于PMP这套知识体系&#xff0c;是一套底层的项目管理逻辑框架&#xff0c;整体是比较抽象的。大家在学习工作之后&#xff0c;会有人告诉你很多职场的一些做事的规则&#xff0c;比如说对于沟通&#xff0c;有人就会告诉如何跟客户沟通跟同事相处等等&#xff0c;这其实就…...

AVR128单片机 USART通信控制发光二极管显示

一、系统方案 二、硬件设计 原理图如下&#xff1a; 三、单片机软件设计 1、首先是系统初始化 void port_init(void) { PORTA 0xFF; DDRA 0x00;//输入 PORTB 0xFF;//低电平 DDRB 0x00;//输入 PORTC 0xFF;//低电平 DDRC 0xFF;//输出 PORTE 0xFF; DDRE 0xfE;//输出 PO…...

为什么5G 要分离 CU 和DU?(4G分离RRU 和BBU)

在 Blog 一文中&#xff0c;5G--BBU RRU 如何演化到 CU DU&#xff1f;_5g rru_qq_38480311的博客-CSDN博客 解释了4G的RRU BBU 以及 5G CU DU AAU&#xff0c;主要是讲了它们分别是什么。但是没有讲清楚 为什么&#xff0c;此篇主要回答why。 4G 为什么分离基站为 RRU 和 BBU…...

Python中的数据输入

获取键盘输入 input语句 使用input()可以从键盘获取输入&#xff0c;使用一个变量来接收 print("你是谁&#xff1f;") name input() print(f"我知道了&#xff0c;你是{name}")# print("你是谁&#xff1f;") name input("你是谁&…...

cms系统稳定性压力测试出现TPS抖动和毛刺的性能bug【杭州多测师_王sir】

一、并发线程数100&#xff0c;分10个阶梯&#xff0c;60秒加载时间&#xff0c;运行1小时进行压测&#xff0c;到10分钟就出现如下 二、通过jstat -gcutil 16689 1000进行监控...

【UE】材质描边、外发光、轮廓线

原教学视频链接&#xff1a; ue4 材质描边、外发光、轮廓线_哔哩哔哩_bilibili 步骤 1. 首先新建一个材质&#xff0c;这里命名为“Mat_outLine” 在此基础上创建一个材质实例 2. 在视口中添加一个后期处理体积 设置后期处理体积为无限范围 点击添加一个数组 选择“资产引用”…...

百模大战,打响AI应用生态的新赛点

点击关注 文&#xff5c;郝鑫 黄小艺&#xff0c;编&#xff5c;刘雨琦 “宇宙中心”五道口&#xff0c;又泛起了昔日的光芒。 十字路口一角的华清嘉园里&#xff0c;各种互联网大佬们&#xff0c;王兴、程一笑、张一鸣等人的创业传说似乎还有余音&#xff0c;后脚搬进来的AI…...

【C++二叉树】进阶OJ题

【C二叉树】进阶OJ题 目录 【C二叉树】进阶OJ题1.二叉树的层序遍历II示例代码解题思路 2.二叉搜索树与双向链表示例代码解题思路 3.从前序与中序遍历序列构造二叉树示例代码解题思路 4.从中序与后序遍历序列构造二叉树示例代码解题思路 5.二叉树的前序遍历&#xff08;非递归迭…...

C++——vector:resize与reserve的区别,验证写入4GB大数据时相比原生操作的效率提升

resize和reserve的区别 reserve&#xff1a;预留空间&#xff0c;但不实例化元素对象。所以在没有添加新的对象之前&#xff0c;不能引用容器内的元素。而要通过调用push_back或者insert。 resize&#xff1a;改变容器元素的数量&#xff0c;且会实例化对象&#xff08;指定或…...

基础配置xml

# 配置端口 server.port8081# 文件上传配置 # 是否支持文件上传 spring.servlet.multipart.enabledtrue # 是否支持文件写入磁盘 spring.servlet.multipart.file-size-threshold0 # 上传文件的临时目录 spring.servlet.multipart.locationd:/opt/tmp # 最大支持上传文件大小 sp…...

win环境安装SuperMap iserver和配置许可

SuperMap iServer是我国北京超图公司研发的基于跨平台GIS内核的云GIS应用服务器产品&#xff0c;通过服务的方式&#xff0c;面向网络客户端提供与专业GIS桌面产品相同功能的GIS服务&#xff0c;能够管理、发布多源服务&#xff0c;包括REST服务、OGC服务等。 SuperMap iserve…...

【Apollo学习笔记】——规划模块TASK之PIECEWISE_JERK_NONLINEAR_SPEED_OPTIMIZER(一)

文章目录 TASK系列解析文章前言PIECEWISE_JERK_NONLINEAR_SPEED_OPTIMIZER功能介绍PIECEWISE_JERK_NONLINEAR_SPEED_OPTIMIZER相关配置PIECEWISE_JERK_NONLINEAR_SPEED_OPTIMIZER流程确定优化变量定义目标函数定义约束ProcessSetUpStatesAndBoundsOptimizeByQPCheckSpeedLimitF…...

pytest parametrize多参数接口请求及展示中文响应数据

编写登陆接口 app.py from flask import Flask, request, jsonify, Responseapp Flask(__name__)app.route(/login, methods[POST]) def login():username request.form.get(username)password request.form.get(password)# 在这里编写你的登录验证逻辑if username admin…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

ubuntu22.04有线网络无法连接,图标也没了

今天突然无法有线网络无法连接任何设备&#xff0c;并且图标都没了 错误案例 往上一顿搜索&#xff0c;试了很多博客都不行&#xff0c;比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动&#xff0c;重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...