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

Java中的动态代理——介绍与使用示例

        Java中的动态代理其实就是一种“代理”模式,在运行时帮我们创建一个“代理对象”,通过这个代理对象可以在不改变原本方法的情况下,做一些额外的事情,比如记录日志、检查权限等。这种代理机制非常灵活和实用,特别是在像Spring框架这种大项目中,经常用于AOP(面向切面编程)——让我们在不打扰核心业务逻辑的情况下插入一些其他功能。

1. 什么是动态代理?

        首先,我们需要理解“代理”这个概念。
        假设你想找一个明星签名,但明星不可能亲自和每个人打交道,于是就雇佣了一个经纪人,这个经纪人就充当了代理。你和经纪人打交道,但实际上签名的事情经纪人会去和明星沟通,完成签名工作。
        Java中的动态代理也是类似的,它创建了一个代理对象,你调用这个代理对象的方法时,实际执行的可能是原本对象的方法,但在执行的前后,代理对象还可以做一些其他的事情。

2. Java动态代理的核心

        在Java中,动态代理有两个核心组件:

  • 代理类(Proxy Class):Java通过Proxy类来生成代理对象,这个代理对象会代理目标对象的行为。
  • InvocationHandler接口:所有被代理的方法调用,都会被转到这个接口的invoke()方法里面去处理。你可以在invoke()方法里做任何你想做的事情,比如添加日志、修改方法的输入输出等。

3. 动态代理是怎么工作的?

        要理解动态代理,先来看几个步骤:

  • 目标对象:这是你想要代理的实际对象,比如一个服务类,执行某个任务。
  • 代理对象:这是由Java动态生成的,它和目标对象长得一样,实现了同样的接口。你通过它来调用方法,但实际背后是代理对象把这些调用转发给了目标对象。
  • 调用处理器(InvocationHandler):代理对象每次调用方法时,都会被“拦截”,实际的执行是由InvocationHandler里的invoke()方法来决定的。在这里你可以加入自己的逻辑,比如方法前后打印日志、检查权限等,然后再调用目标对象的方法。

4. 代码示例:一步步搞懂

        让我们通过一个简单的例子来理解动态代理的工作原理。

        假设你有一个服务接口Service,它有一个简单的方法doSomething()

public interface Service {void doSomething();
}

        然后你实现了这个接口:

public class ServiceImpl implements Service {@Overridepublic void doSomething() {System.out.println("执行一些操作");}
}

5. 如何使用动态代理?

        假设你想在执行doSomething()之前和之后打印一些日志信息,通常你可能需要手动去修改代码,但这会让代码变得不容易维护。使用动态代理可以帮助你在不修改目标对象代码的情况下实现这一功能。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class DynamicProxyExample {public static void main(String[] args) {// 创建目标对象Service target = new ServiceImpl();// 使用代理对象增强功能Service proxy = (Service) Proxy.newProxyInstance(target.getClass().getClassLoader(), // 类加载器target.getClass().getInterfaces(),  // 实现的接口new InvocationHandler() {           // 调用处理器@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("方法执行前:记录日志");Object result = method.invoke(target, args); // 调用目标对象的方法System.out.println("方法执行后:记录日志");return result;}});// 通过代理对象调用方法proxy.doSomething();}
}

6. 解释代码

  • Proxy.newProxyInstance():这个方法会为你创建一个代理对象。它需要三个参数:

    • ClassLoader:用来加载代理类的类加载器。一般使用目标对象的类加载器。
    • Class[]:目标对象实现的接口列表。代理对象会实现这些接口。
    • InvocationHandler:这是调用处理器,你可以定义代理对象方法的行为。
  • InvocationHandler.invoke():每次代理对象的方法被调用,实际都会进入这个invoke()方法。这里你可以在方法调用前后做一些其他的操作,比如打印日志,最后调用目标对象的方法。

7. 输出结果

        运行上面的代码,你会看到这样的输出:

方法执行前:记录日志
执行一些操作
方法执行后:记录日志

        这个代理对象不仅执行了doSomething()方法,还在方法前后加上了日志记录,且不需要修改ServiceImpl的代码,这就是动态代理的强大之处。

8. 动态代理的优点

  • 解耦:你可以在不修改目标对象的情况下,增加额外的功能,保持代码的干净和可维护性。
  • 灵活:你可以动态地决定代理对象的行为,比如在某些条件下添加不同的功能。
  • 常用于AOP:比如在Spring中,动态代理经常用于AOP,帮我们处理事务、日志、安全检查等。

9. 使用场景

  • 日志记录:动态代理可以在每个方法执行前后记录日志,跟踪应用的执行情况。
  • 事务管理:可以在方法执行前开启事务,执行完后提交或回滚。
  • 权限校验:在某些方法执行前,可以检查用户是否有权限执行该操作。
  • 远程调用:通过代理对象调用远程的服务,而不需要修改业务逻辑。

        Java的动态代理为我们提供了一种非常灵活、强大的方法来增强代码的功能,而不必改变现有的代码结构。

相关文章:

Java中的动态代理——介绍与使用示例

Java中的动态代理其实就是一种“代理”模式,在运行时帮我们创建一个“代理对象”,通过这个代理对象可以在不改变原本方法的情况下,做一些额外的事情,比如记录日志、检查权限等。这种代理机制非常灵活和实用,特别是在像…...

微信开发者工具:音乐小程序报错

报错信息 GET http://localhost:3000/1.mp3 net::ERR CONNECTION REFUSED (env: Windows,mp,1.06.2303220;lib:3.6.0) 原因:小程序没有直接获取本地文件,为了提高访问速度,而采用放到网络服务器中网络访问的方式获取文件内容 解决办法&#…...

P2-3与P2-4.【C语言基本数据类型、运算符和表达式】第三节与第四节

讲解视频: P2-3.【基本数据类型、运算符和表达式】第三节 P2-4.【基本数据类型、运算符和表达式】第四节 目录 必备知识与理论 任务实施 必备知识与理论 C语言中把除了控制语句和输入输出以外的几乎所有的基本操作都作为运算符处理。 其运算符和表达式数量之多&a…...

Python | Leetcode Python题解之第492题构造矩形

题目: 题解: class Solution:def constructRectangle(self, area: int) -> List[int]:w int(sqrt(area))while area % w:w - 1return [area // w, w]...

新版vs code + Vue高亮、语法自动补全插件

vs code 版本或及以上 安装以下三个插件插件 Vetur Vue语法支持。包括语法高亮、语法代码提示、语法lint检测 ESLint语法纠错 Prettier 2.左下角设置 3.进行配置 配置内容: {"editor.fontSize": 20,"window.zoomLevel": 1,"workben…...

【优选算法】(第四十五篇)

目录 地图分析(medium) 题目解析 讲解算法原理 编写代码 课程表(medium) 题目解析 讲解算法原理 编写代码 地图分析(medium) 题目解析 1.题目链接:. - 力扣(LeetCode&#…...

自闭症儿童的康复与培养:揭秘有效方法

在生命的广阔画卷中,每一个孩子都是独一无二的色彩,他们带着各自的使命和梦想,踏上人生的旅程。然而,对于自闭症儿童而言,这段旅程似乎更加崎岖和艰难。幸运的是,星贝育园康复中心如同一盏明灯,…...

rom定制系列------小米8澎湃os1.0.28安卓13客户定制固件 刷写以及界面预览

💝💝💝 小米8后置指纹版,机型代码dipper, 官方最终版为12.5.2安卓10的版本。对于一些工作室不太适用。客户需要应用在安卓13的固件。根据客户提供的固件将卡刷改为线刷。并且修改其中客户需求。去除不需要的内置应用以…...

【CTF-SHOW】Web入门 Web14 【editor泄露-详】【var/www/html目录-详】

editor泄露问题通常出现在涉及文件编辑器或脚本编辑器的题目中,尤其是在Web安全或Pwn(系统漏洞挖掘)类别中。editor泄露的本质是由于系统未能妥善处理临时文件、编辑历史或进程信息,导致攻击者可以通过某种途径获取正在编辑的敏感…...

Chrome谷歌浏览器禁止空格下翻页但可以暂停和播放视频脚本js

前提 播放某些网站的视频的时候(不能网页全屏的视频) 会产生空格下翻页但是不能暂停播放视频,解决方案:下载油猴或者脚本猫把这代码填进去 (function() {use strict;document.body.onkeydown function(event) {var e window.event || event;// 检查是否按下空格…...

【笔记】【YOLOv10图像识别】自动识别图片、视频、摄像头、电脑桌面中的花朵学习踩坑

(一)启动 创建环境python3.9 打开此环境终端 (后面的语句操作几乎都在这个终端执行) 输入up主提供的语句:pip install -r requirements.txt 1.下载pytorch网络连接超时 pytorch网址: Start Locally | P…...

H-TCP 的效率和公平性

昨晚带安孩楼下玩耍,用手机 desmos 作了一组 response curve 置于双对数坐标系: 长肥管道的优化思路都很类似,cwnd 增长快一点: BIC TCP:二分查找逼近 capacity;CUBIC TCP:上凸曲线逼近 capa…...

集群与分布式

Cluster(集群)概述 当单独一台主机无法承载现有的用户请求量;或者一台主机因为单一故障导致业务中断的时候,就可以增加服务主机数,这些主机在一起提供服务,就叫集群,而用户所看到的依然是单个的主机,用户并…...

git rebase的常用场景: 交互式变基, 变基和本地分支基于远端分支的变基

文章目录 作用应用场景场景一:交互式变基(合并同一条线上的提交记录) —— git rebase -i HEAD~2场景二:变基(合并分支) —— git rebase [其他分支名称]场景三:本地分支与远端分支的变基 作用 使git的提交记录变得更加简洁 应用场景 场景…...

HttpURLConnection构造请求体传文件

HttpURLConnection构造请求体传文件 在Java中,使用HttpURLConnection构造请求体传输文件,你需要做以下几步: 1、创建URL对象指向你想要请求的资源。 2、通过URL打开连接,转换为HttpURLConnection实例。 3、设置请求方法为POST。 …...

STM32传感器模块编程实践(九) VL53L0X激光红外测距传感器简介及驱动源码

文章目录 一.概要二.VL53L0X测距原理三.VL53L0X主要特性四.VL53L0X硬件参考设计五.模块接线说明六.模块通讯协议介绍七.光学盖玻片介绍八.STM32单片机与VL53L0模块实现距离测量实验1.硬件准备2.软件工程3.软件主要代码4.实验效果 九.小结 一.概要 VL53L0X是一款由ST&#xff0…...

fastjson注解说明,fastjson注解有那些?fastjson是java的json序列化和反序列化工具包

fastjson注解说明,fastjson注解有那些?fastjson是java的json序列化和反序列化工具包 包版本说明 fastjson请使用1.2.83以上版本,小于这个版本的存在漏洞。 fastjson请使用1.2.83以上版本,小于这个版本的存在漏洞。 fastjson请使用1.2.83以上版本,小于这个版本的存在漏洞…...

VIT:论文关键点解读与常见疑问

VIT贡献点: 1. 首次将 Transformer 应用于图像识别任务 核心贡献:ViT 论文的最大贡献是提出将原本用于自然语言处理(NLP)的 Transformer 架构成功应用于图像任务。传统的计算机视觉模型主要依赖卷积神经网络(CNN&…...

ArcGIS无插件加载(无偏移)在线天地图高清影像与街道地图指南

在地理信息系统(GIS)的应用中,加载高清影像与街道地图对于地图制图、影像查阅、空间数据分析等工作至关重要。天地图作为官方出品的地图服务,以其标准的数据、较快的影像更新速度等特点受到广泛欢迎。以下是如何在ArcGIS中无插件加…...

工业相机选型(自用笔记)

可参考链接: 相机和镜头选型需要注意哪些问题_靶面尺寸-CSDN博客 工业相机选型方法_ccd工业相机选型步骤-CSDN博客 1、相机 1.1 传感器类型(CCD/CMOS) CCD相机: 1)目标是运动的则优先考虑。 2)需要高质量图像,如进行…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

vscode里如何用git

打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

OpenLayers 可视化之热力图

注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...