【Java 基础】30 JDK动态代理

文章目录

    • 1.定义
    • 2.原理
    • 3.使用
      • 1)定义业务接口
      • 2)实现 InvocationHandler 接口
      • 3)生成代理类
    • 4.优点
    • 5.缺点
    • 总结

动态代理是一种重要的 设计模式,它允许在运行时生成代理类来代替实际的类。动态代理主要通过反射机制实现,为开发者提供了一种灵活且强大的方式来实现 AOP(面向切面编程)等功能。

1.定义

动态代理是一种在运行时生成代理类的机制,这些代理类在程序运行时创建,而不是在编译时静态定义。 JDK 动态代理主要基于 Java 的反射机制,通过在运行时创建代理类和对象,实现对实际类的代理。

动态代理通常用于在不修改原始类代码的情况下,向现有类添加额外的功能,例如日志记录性能监控事务处理等。

2.原理

JDK 动态代理的核心在于 java.lang.reflect 包中的 Proxy 类和 InvocationHandler 接口。代理类的创建过程主要包括以下步骤:

在这里插入图片描述

  • 定义接口: 定义一个业务接口,该接口将被动态代理类实现。
  • 实现 InvocationHandler 接口: 创建一个实现 InvocationHandler 接口的类,该类中包含了对原始类方法的代理逻辑。
  • 生成代理类: 使用 Proxy.newProxyInstance 方法生成代理类的实例,该方法需要传入类加载器、业务接口和 InvocationHandler 实现。
  • 调用代理方法: 通过代理类实例调用方法时,实际会调用到 InvocationHandler 中的 invoke 方法,从而执行代理逻辑。

3.使用

1)定义业务接口

interface Stu {void say(String name);
}

2)实现 InvocationHandler 接口

class HelloInvocationHandler implements InvocationHandler {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) {// 增加前处理System.out.println("执行方法前: " + method.getName());// 执行原始方法 saySystem.out.println("Hello, " + args[0]);// 增加后处理System.out.println("执行方法后: " + method.getName());return null;}
}

3)生成代理类

public class Demo {public static void main(String[] args) {// 创建 InvocationHandler 实例HelloInvocationHandler invocationHandler = new HelloInvocationHandler();// 生成代理类实例Stu proxy = (Stu) Proxy.newProxyInstance(Stu.class.getClassLoader(),new Class[] { Stu.class },invocationHandler);// 调用代理方法proxy.say("Cheney");}
}

输出结果:

执行方法前: say
Hello, Cheney
执行方法后: say

在上述示例中,HelloInvocationHandler 类实现了 InvocationHandler 接口,通过在代理方法的前后添加日志记录,这也就是传说中的 AOP 面向切面编程的效果。

4.优点

  • 灵活性: 动态代理可以代理任意实现了接口的类,不受具体类的限制。
  • 简化代码: 动态代理可以避免编写大量重复的代理类代码,减少代码冗余。
  • 解耦合: 动态代理实现了代理逻辑和业务逻辑的解耦,使得代理类可以复用于不同的业务场景。

5.缺点

  • 只能代理接口: JDK 动态代理只能代理实现了接口的类,对于没有实现接口的类无法进行代理。
  • 性能相对较低: 由于动态代理是在运行时生成代理类,因此相比静态代理,其性能相对较低。

总结

JDK 动态代理是一种强大而灵活的设计模式,它通过在运行时生成代理类来实现对实际类的代理,为实现 AOP 等功能提供了便捷的方式。通过使用 Proxy 类和 InvocationHandler 接口,开发者可以轻松地创建动态代理。虽然 JDK 动态代理有一些限制,如只能代理实现了接口的类,性能相对较低等,但在大多数场景下,其优势远远大于缺点,使得它成为 Java 编程中不可或缺的一部分。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker入门安装gerrit软件

Windows上运行docker 什么是Docker Desktop docker desktop是Docker在Windows 10和macOS操作系统上的官方安装方式,这个方法依然属于先在 Windows 上部署 Docker 的方法都是先安装一个虚拟机,并在安装 Linux 系统的的虚拟机中运行 Docker。 开启Hyper-…

BluetoothDevice 序列化问题

文章目录 前言思考分析定位 前言 在做蓝牙设备通信时,遇到一个奇葩的问题,公司另一个部门开发的蓝牙组件库,把蓝牙设备BluetoothDevice进行了序列化,在连接时候又进行反序列化。但是当我去调试我的项目时,发现发序列化…

【每日一题】最小体力消耗路径

文章目录 Tag题目来源解题思路方法一:二分枚举答案 写在最后 Tag 【二分枚举答案】【图】【2023-12-11】 题目来源 1631. 最小体力消耗路径 解题思路 拿到这个题目,计算从左上角到右下角的最小体力消耗值,有点像 64. 最小路径和。在 64 题…

以太坊:前世今生与未来

一、引言 以太坊,这个在区块链领域大放异彩的名字,似乎已经成为了去中心化应用(DApps)的代名词。从初期的萌芽到如今的繁荣发展,以太坊经历了一段曲折而精彩的旅程。让我们一起回顾一下以太坊的前世今生,以…

C# 任务的异常和延续处理

写在前面 当Task在执行过程中出现异常或被取消等例外的情况时,为了让执行流程能够继续进行,可以使用延续方法实现这种链式处理;还可以针对前置任务不同的执行结果,选择执行不同的延续分支方法。子任务执行过程中的任何异常都会被…

分页设计(平时在表下面的栏框,有首页 | 上一页 | 下一页 | 尾页),下面代码带你实现

分页设计的本质就是,分页查询,就是SQL语句当中的(select * from ? limit ? , ?),这里第一个?是所分页的那张表 ,第二个?从哪条开始,第三个?是在页面上想让这张表出现几…

老师们居然这样把考试成绩发给家长

教育是一个复杂而多元的过程,其中考试成绩的发布和沟通是教育过程中的一个重要环节。然而,有些老师在发布考试成绩时,采取了一些不恰当的方式,给家长和学生带来了不必要的困扰和压力。本文将探讨老师们不应该采取的发布考试成绩的…

MSPM0L1306例程学习-ADC部分(1)

MSPM0L1306例程学习-ADC部分(1) MSPM0L1306例程学习 使用的TI的官方例程,即SDK里边包含的例程代码。 MCU使用的是MSPM0L1306, 对于ADC部分,有10个例程: 例程理解 ADC的转换有多种工作模式,从最简单的单通道单次转换开始入手…

远程控制如何赋能智能制造?贝锐向日葵制造业场景案例解析

随着数字化转型在制造业的不断深入,企业在产线端也逐渐投入更多智能化设备,数字化、智能化设备其中一个比较显著的优势就是可以依托互联网实现远程运维和调试,大大提升产线设备的稳定性和工作效率;而远程调试运维一个重要的实现方…

Spring Cache【娓娓道来】

目录​​​​​​​ 1.自我介好😳😳😳 2.常用注解 💕💕💕 3.EnableCaching🤦‍♂️🤦‍♂️🤦‍♂️ 4.CachePut🤷‍♀️🤷‍♀️&#x1f93…

.9.png编译报错

android项目中使用9-patch图编译报错:AAPT: error: file failed to compile. 原因是因为.9.png图中有线之间断开或者黑点的存在,把线连上或者把黑点去掉就可以了。如下:

云降水物理基础

云降水物理基础 云的分类 相对湿度变化方程 由相对湿度的定义,两边取对数之后可以推出 联立克劳修斯-克拉佩龙方程(L和R都为常数) 由右式看出,增加相对湿度的方式:增加水汽(de增大)和降低…