动态代理初步了解
准备案例
需求
模拟某企业用户管理业务,需包含用户登录,用户删除,用户查询功能,并要统计每个功能的耗时。
分析与实现
定义一个UserService表示用户业务接口,规定必须完成用户登录,用户删除,用户查询功能。
/**模拟用户业务功能*/
public interface UserService {String login(String loginName , String passWord) ;void selectUsers();boolean deleteUsers();void updateUsers();
}
定义一个实现类UserServiceImpl实现UserService,并完成相关功能,且统计每个功能的耗时。
public class UserServiceImpl implements UserService{@Overridepublic String login(String loginName, String passWord) {long startTimer = System .currentTimeMillis();try {Thread.sleep(1000);if("admin".equals(loginName) && "1234".equals(passWord)) {return "success";}return "登录名和密码可能有毛病";} catch (Exception e) {e.printStackTrace();return "error";}finally{long endTimer = System.currentTimeMillis();System.out.println("login方法耗时:" + (endTimer - startTimer) / 1000.0 + "s");}}@Overridepublic void selectUsers() {long startTimer = System .currentTimeMillis();System.out.println("查询了100个用户数据!");try {Thread.sleep(2000);} catch (Exception e) {e.printStackTrace();}finally{long endTimer = System.currentTimeMillis();System.out.println("selectUsers方法耗时:" + (endTimer - startTimer) / 1000.0 + "s");}}@Overridepublic boolean deleteUsers() {long startTimer = System .currentTimeMillis();try {System.out.println("删除100个用户数据!");Thread.sleep(500);return true;} catch (Exception e) {e.printStackTrace();return false;}finally{long endTimer = System.currentTimeMillis();System.out.println("deleteUsers方法耗时:" + (endTimer - startTimer) / 1000.0 + "s");}}@Overridepublic void updateUsers() {long startTimer = System .currentTimeMillis();try {System.out.println("修改100个用户数据!");Thread.sleep(2500);} catch (Exception e) {e.printStackTrace();}finally{long endTimer = System.currentTimeMillis();System.out.println("updateUsers方法耗时:" + (endTimer - startTimer) / 1000.0 + "s");}}
}
定义测试类,创建实现类对象,调用方法。
public class Test {public static void main(String[] args) {UserService userService = new UserServiceImpl();System.out.println(userService.login("admin", "1234"));System.out.println(userService.deleteUsers());userService.selectUsers();userService.updateUsers();}
}
提出问题
业务对象的的每个方法都要进行性能统计,存在大量重复的代码。
使用动态代理解决问题
动态代理
代理就是被代理者没有能力或者不愿意去完成某件事情,需要找个人代替自己去完成这件事,动态代理就是用来对业务功能(方法)进行代理的。
关键步骤
1.必须有接口,实现类要实现接口(代理通常是基于接口实现的)。
2.创建一个实现类的对象,该对象为业务对象,紧接着为业务对象做一个代理对象。
代理过程
当我们要对login方法进行耗时统计时,先进入代理对象,然后统计开始时间,接着真正执行登录方法,最后统计结束时间,如下图所示:
代码
接口不用变,修改实现类和测试类,增加一个代理工具类,如下:
public class UserServiceImpl implements UserService{@Overridepublic String login(String loginName, String passWord) {try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}if("admin".equals(loginName) && "1234".equals(passWord)) {return "success";}return "登录名和密码可能有毛病";}@Overridepublic void selectUsers() {System.out.println("查询了100个用户数据!");try {Thread.sleep(2000);} catch (Exception e) {e.printStackTrace();}}@Overridepublic boolean deleteUsers() {try {System.out.println("删除100个用户数据!");Thread.sleep(500);return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic void updateUsers() {try {System.out.println("修改100个用户数据!");Thread.sleep(2500);} catch (Exception e) {e.printStackTrace();}}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)参数一:类加载器,负责加载代理类到内存中使用。参数二:获取被代理对象实现的全部接口。代理要为全部接口的全部方法进行代理参数三:代理的核心处理逻辑*/
public class ProxyUtil {/**生成业务对象的代理对象。* @param obj* @return*/public static <T> T getProxy(T obj) {// 返回了一个代理对象了return (T)Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 参数一:代理对象本身。一般不管// 参数二:正在被代理的方法// 参数三:被代理方法,应该传入的参数long startTimer = System .currentTimeMillis();// 马上触发方法的真正执行。(触发真正的业务功能)Object result = method.invoke(obj, args);long endTimer = System.currentTimeMillis();System.out.println(method.getName() + "方法耗时:" + (endTimer - startTimer) / 1000.0 + "s");// 把业务功能方法执行的结果返回给调用者return result;}});}
}
public class Test {public static void main(String[] args) {// 1、把业务对象,直接做成一个代理对象返回,代理对象的类型也是 UserService类型UserService userService = ProxyUtil.getProxy(new UserServiceImpl());System.out.println(userService.login("admin", "1234"));System.out.println(userService.deleteUsers());userService.selectUsers();userService.updateUsers(); // 走代理}
}
动态代理的优点
非常的灵活,支持任意接口类型的实现类对象做代理,也可以直接为接口本身做代理。
可以为被代理对象的所有方法做代理。
可以在不改变方法源码的情况下,实现对方法功能的增强。
不仅简化了编程工作、提高了软件系统的可扩展性,同时也提高了开发效率。
相关文章:
动态代理初步了解
准备案例 需求 模拟某企业用户管理业务,需包含用户登录,用户删除,用户查询功能,并要统计每个功能的耗时。 分析与实现 定义一个UserService表示用户业务接口,规定必须完成用户登录,用户删除,…...
QT国际化
引入 在代码里面写中文就很low,运行时多语言切换是客户端程序都应该具备的。 qt国际化其实就是qt中字符串的字符集编码的设置。当然这个设置不是简单的选择一下什么语言就好,这个需要编程人员来处理的。 通常对于非拉丁字符(主要指latin1字符…...
微信小程序button按钮去除边框去除背景色
button边框 去除button边框 在button上添加plain“true”在css中添加button.avatar-wrapper {background: none}用于去除button背景色在css中添加button.avatar-wrapper[plain]{ border:0 }用于去除button边框...
Neo4j深度学习
Neo4j的简介 Neo4j是用Java实现的开源NoSQL图数据库。从2003年开始开发,2007年正式发布第一版,其源码托管于GitHtb。Neo4j作为图数据库中的代表产品,已经在众多的行业项目中进行了应用,如:网络管理、软件分析、组织和…...
【数据结构C/C++】链式存储与顺序存储结构栈
文章目录 链式存储结构顺序存储结构 下面这篇文章是我大二时候写的比较详细的实现过程,再这篇文章我也会再一次比较简单的再次简述一下链式与顺序存储结构的实现方式。 链式存储结构与顺序存储结构详解 这里我就不使用C再一次实现这两个栈了,有兴趣的也可…...
【数据库系统概论】数据定义之基本表的定义/创建、修改和删除
前言 🚩定义/创建基本表语法示例 修改基本表语法示例 删除基本表语法示例 感谢 💖 前言 🚩 SQL支持数据库系统的三级模式结构,其模式、外模式和内模式中的基本对象有表、视图和索引,因此,SQL的数据定义功能…...
面试算法22:链表中环的入口节点(1)
题目 如果一个链表中包含环,那么应该如何找出环的入口节点?从链表的头节点开始顺着next指针方向进入环的第1个节点为环的入口节点。 例如,在如图4.3所示的链表中,环的入口节点是节点3。 分析 第1步:确认是否包含环…...
蓝桥杯---第二讲---二分与前缀和
文章目录 前言Ⅰ. 数的范围0x00 算法思路0x00 代码书写 Ⅱ. 数的三次方根0x00 算法思路0x01代码书写 Ⅲ. 前缀和0x00 算法思路0x01 代码书写 Ⅳ. 子矩阵的和0x00 算法思路0x01 代码书写 Ⅴ. 机器人跳跃问题0x00 算法思路0x01 代码书写 Ⅵ. 四平方和0x00 算法思路0x01 代码书写 …...
d3dx9_39.dll如何修复?最新修复d3dx9_39.dll方法分享
大家好!今天我要和大家分享的主题是“d3dx9_39.dll丢失的修复方法”。我们都知道,在使用电脑的过程中,经常会遇到各种问题,而其中最常见的就是文件丢失。d3dx9_39.dll就是其中一个常见的丢失文件。那么,如何修复这个丢…...
阿里云轻量应用服务器月流量限制说明(部分套餐不限流量)
阿里云轻量应用服务器部分套餐限制月流量,轻量应用服务器按照套餐售卖,有的套餐限制月流量,有的不限制流量。像阿里云轻量2核2G3M带宽轻量服务器一年108元和轻量2核4G4M带宽一年297.98元12个月,这两款是不限制月流量的。阿里云百科…...
项目设计:YOLOv5目标检测+机构光相机(intel d455和d435i)测距
1.介绍 1.1 Intel D455 Intel D455 是一款基于结构光(Structured Light)技术的深度相机。 与ToF相机不同,结构光相机使用另一种方法来获取物体的深度信息。它通过投射可视光谱中的红外结构光图案,然后从被拍摄物体表面反射回来…...
WPF中DataContext的绑定技巧
先看效果: 上面的绑定值都是我们自定义的属性,有了以上的提示,那么我们可以轻松绑定字段,再也不用担心错误了。附带源码。 目录 1.建立mvvm项目 2.cs后台使用DataContext绑定 3.xaml前台使用DataContext绑定 4.xaml前台使用Da…...
【Spring MVC研究】MVC原理:DispatcherServlet的初始化,初始化好等于MVC准备好
文章目录 1. EnableWebMVC 开启 MVC 功能2. 初始化自定义的 MVC 组件2.1. 初始化过程2.2. 如何分析复杂的 Spring 组件注册 3. 容器启动后会初始化 DispatcherServlet4. DispatcherServlet 初始化过程总结5. 资料参考 把DispatcherServlet 准备好意味着服务器已经可以处理请求了…...
Kafka的分布式架构与高可用性
导语 一开始我们就说过Kafka是一款开源的高吞吐、分布式的消息队列系统,那么今天我们就来说下它的分布式架构和高可用性以及双/多中心部署。 Kafka 体系架构简介 以下是 Kafka 的软件架构,整个 Kafka 体系结构由 Producer、Consumer、Broker、ZooKeepe…...
Spring Cloud学习笔记【分布式请求链路跟踪-Sleuth】
文章目录 Spring Cloud Sleuth概述概述主要功能:Sleuth中的术语和相关概念官网 zipkin配置下载运行zipkin下载zipkin运行 demo配置服务提供者 lf-userpom.xmlapplication.ymlUserController 服务调用者 lf-authpom.xmlapplication.ymlAuthController 测试 Spring Cl…...
Java开发中的操作日志详解(InsCode AI 创作助手)
Java开发中的操作日志详解 一、操作日志的作用 故障排除和调试: 操作日志可以记录应用程序的各种活动,包括错误、异常、警告和信息性消息。这有助于开发人员快速定位和解决问题。性能分析: 通过记录关键操作和性能指标,操作日志…...
FutureTask和CompletableFuture的模拟使用
模拟了查询耗时操作,并使用FutureTask和CompletableFuture分别获取计算结果,统计执行时长 package org.alllearn.futurtask;import com.google.common.base.Stopwatch; import com.google.common.collect.Lists; import lombok.AllArgsConstructor; imp…...
Redis作为缓存,mysql的数据如何与redis进行同步?
Redis作为缓存,mysql的数据如何与redis进行同步? 一定要设置前提,先介绍业务背景 延时双删 双写一致性:当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致 读操作:缓存命中,直接返回;缓存未…...
申请免费 SSL 证书为您的小程序加密通信
在今天的网络环境中,数据安全和隐私保护变得尤为重要。无论是网站还是应用程序,为其提供安全的通信渠道都是至关重要的。对于小程序开发者来说,使用 SSL(Secure Sockets Layer)证书可以有效地保障用户数据的安全&#…...
Go 并发编程
并发编程 1.1 并发与并⾏ 并⾏与并发是两个不同的概念,普通解释: 并发:交替做不同事情的能⼒并⾏:同时做不同事情的能⼒ 如果站在程序员的⻆度去解释是这样的: 并发:不同的代码块交替执⾏并⾏…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究
摘要:在消费市场竞争日益激烈的当下,传统体验营销方式存在诸多局限。本文聚焦开源AI智能名片链动2 1模式S2B2C商城小程序,探讨其在沉浸式体验营销中的应用。通过对比传统品鉴、工厂参观等初级体验方式,分析沉浸式体验的优势与价值…...
Django RBAC项目后端实战 - 03 DRF权限控制实现
项目背景 在上一篇文章中,我们完成了JWT认证系统的集成。本篇文章将实现基于Redis的RBAC权限控制系统,为系统提供细粒度的权限控制。 开发目标 实现基于Redis的权限缓存机制开发DRF权限控制类实现权限管理API配置权限白名单 前置配置 在开始开发权限…...
算法刷题-回溯
今天给大家分享的还是一道关于dfs回溯的问题,对于这类问题大家还是要多刷和总结,总体难度还是偏大。 对于回溯问题有几个关键点: 1.首先对于这类回溯可以节点可以随机选择的问题,要做mian函数中循环调用dfs(i&#x…...
Shell 解释器 bash 和 dash 区别
bash 和 dash 都是 Unix/Linux 系统中的 Shell 解释器,但它们在功能、语法和性能上有显著区别。以下是它们的详细对比: 1. 基本区别 特性bash (Bourne-Again SHell)dash (Debian Almquist SHell)来源G…...
