Java基础学习: JDK动态代理

文章目录

  • 一、什么是JDK动态代理
  • 二、JDK动态代理的特点
  • 三、JDK动态代理类如何使用
  • 四、JDK动态代理原理分析
    • 1、创建代理对象
    • 2、生成代理类

一、什么是JDK动态代理

JDK动态代理是Java提供的一种动态生成代理类和代理对象的技术。它主要利用Java的反射机制实现,在运行时动态地创建代理类,并为其生成代理对象。JDK动态代理主要用于实现AOP(面向切面编程)等场景,用于在不修改目标类代码的情况下,为目标类添加额外的功能。

二、JDK动态代理的特点

  • 基于接口代理:JDK动态代理只能为接口创建代理实例,不能针对类创建代理实例。如果要为类创建代理,可以考虑使用CGLIB等第三方库。
  • 运行时生成代理类:JDK动态代理在运行时动态地创建代理类,无需提前编译。
  • 代理类和代理对象:JDK动态代理不仅生成代理类,还生成代理对象。代理对象实现了目标接口,并将目标对象作为参数传递给InvocationHandler。

三、JDK动态代理类如何使用

  • 定义接口和目标类:首先,你需要定义一个接口和一个实现了该接口的目标类。
public interface MyInterface {  void doSomething();  
}  public class MyTarget implements MyInterface {  @Override  public void doSomething() {  System.out.println("Target method executed.");  }  
}
  • 创建InvocationHandler:实现InvocationHandler接口,并在invoke方法中编写代理逻辑。invoke方法会在调用代理对象的任何方法时被调用
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  public class MyInvocationHandler implements InvocationHandler {  private Object target;  public MyInvocationHandler(Object target) {  this.target = target;  }  @Override  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  System.out.println("Before method execution.");  Object result = method.invoke(target, args);  System.out.println("After method execution.");  return result;  }  
}
  • 创建代理对象:使用Proxy.newProxyInstance方法创建代理对象。这个方法需要三个参数:类加载器、代理类实现的接口列表和InvocationHandler实例。
import java.lang.reflect.Proxy;  public class Main {  public static void main(String[] args) {  MyInterface target = new MyTarget();  MyInvocationHandler handler = new MyInvocationHandler(target);  MyInterface proxy = (MyInterface) Proxy.newProxyInstance(  target.getClass().getClassLoader(),  target.getClass().getInterfaces(),  handler  );  proxy.doSomething(); // 执行代理对象的方法  }  
}

执行上述代码,你会看到在调用doSomething方法前后,都输出了日志信息,这就是通过JDK动态代理实现的AOP效果。

需要注意的是,由于JDK动态代理基于接口,因此如果你的目标类没有实现任何接口,那么JDK动态代理将无法使用。在这种情况下,你可以考虑使用CGLIB等第三方库来创建代理。

四、JDK动态代理原理分析

1、创建代理对象

对于匿名类方法中的实例,会在改类型为其生成相应的变量
在这里插入图片描述

2、生成代理类

生成的代理对象继承了Proxy类,并实现了UserService接口。

  • 接口
public interface UserService {void test();void getOne();void getById();
}
  • 接口实现类
import person.xsc.source.read.service.UserService;public class UserServiceImpl implements UserService {@Overridepublic void test() {System.out.println("hello world");}@Overridepublic void getOne() {}@Overridepublic void getById() {}
}
  • 生成$proxy0类
import sun.misc.ProxyGenerator;import java.io.FileOutputStream;
import java.io.IOException;public class ProxyDemo {public static void main(String[] args) {UserServiceImpl userService = new UserServiceImpl();byte[] proxyClassFile = ProxyGenerator.generateProxyClass("$proxy0", userService.getClass().getInterfaces(), 1);FileOutputStream outputStream = null;try {outputStream = new FileOutputStream("D:\\myProject\\spring-yuanma-fenxi\\src\\test\\java\\proxy\\$proxy0.class");outputStream.write(proxyClassFile);outputStream.flush();} catch (Exception e) {e.printStackTrace();} finally {try {outputStream.close();} catch (IOException e) {e.printStackTrace();}}}
}
  • 展示$proxy0类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import person.xsc.source.read.service.UserService;public class $proxy0 extends Proxy implements UserService {private static Method m1;private static Method m3;private static Method m4;private static Method m2;private static Method m5;private static Method m0;public $proxy0(InvocationHandler var1) throws  {super(var1);}public final boolean equals(Object var1) throws  {try {return (Boolean)super.h.invoke(this, m1, new Object[]{var1});} catch (RuntimeException | Error var3) {throw var3;} catch (Throwable var4) {throw new UndeclaredThrowableException(var4);}}public final void test() throws  {try {super.h.invoke(this, m3, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final void getById() throws  {try {super.h.invoke(this, m4, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final String toString() throws  {try {return (String)super.h.invoke(this, m2, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final void getOne() throws  {try {super.h.invoke(this, m5, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final int hashCode() throws  {try {return (Integer)super.h.invoke(this, m0, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}static {try {m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));m3 = Class.forName("person.xsc.source.read.service.UserService").getMethod("test");m4 = Class.forName("person.xsc.source.read.service.UserService").getMethod("getById");m2 = Class.forName("java.lang.Object").getMethod("toString");m5 = Class.forName("person.xsc.source.read.service.UserService").getMethod("getOne");m0 = Class.forName("java.lang.Object").getMethod("hashCode");} catch (NoSuchMethodException var2) {throw new NoSuchMethodError(var2.getMessage());} catch (ClassNotFoundException var3) {throw new NoClassDefFoundError(var3.getMessage());}}
}

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

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

相关文章

国产AI大模型推荐(一)

文心一言 主要功能: 各种类型的问答、各种文本创作、推理与数学计算、写代码、聊天交流、图片生成等。 链接:文心一言 讯飞星火 特点: 内容生成能力:我可以进行多风格多任务长文本生成,例如邮件、文案、公文、作文、对…

HTTPS传输过程

HTTPS:超文本传输安全协议 相较于HTTP明文传输,HTTPS增加了SSL/TLS进行了加密增加了通信的安全性。 SSL和TLS是两个不同的加密方法,SSL是TLS的前身,现在绝大多数浏览器使用的是TLS,所以着重了解以下TLS的概念即可。 首…

centos 7 安装磐维(PanWeiDB)数据库(单机)

前置环境准备 文件系统环境要求 文件系统环境所要求的扇区必须为512bytes,查看方法如下: [rootdevops-core-highapp3-b-32 ~]#df -h /apps/ [rootdevops-core-highapp3-b-32 ~]#ll /dev/mapper/vg--docker-lvapp [rootdevops-core-highapp3-b-32 ~]#f…

EfficientNetV2:谷歌又来了,最小的模型,最高的准确率,最快的训练速度 | ICML 2021

论文基于training-aware NAS和模型缩放得到EfficientNetV2系列,性能远优于目前的模型。另外,为了进一步提升训练速度,论文提出progressive learning训练方法,在训练过程中同时增加输入图片尺寸和正则化强度。从实验结果来看&#…

【docker】nexus 本地 maven配置

1、这篇文章中说明了如何搭建私服 【docker】搭建Nexus私服-CSDN博客文章浏览阅读2次。4、点击登陆(账号:admin 秘密:在容器内 /nexus-data/admin.password 文件中)注意我的端口号是 10002,注意你的端口号。7、设置maven-central…

MSTP环路避免实验(华为)

思科设备参考:MSTP环路避免实验(思科) 一,技术简介 MSTP(多生成树协议),MSTP解决了STP和RSTP没有考虑vlan的问题,STP和RSTP将所有的vlan共享为一个生成树实例,无法实现…

获取电商数据的几种方法分享

在数字化时代,电商数据已经成为企业决策的重要依据。无论是市场趋势的洞察、用户行为的分析,还是产品优化和营销策略的制定,都离不开电商数据的支持。本文将分享几种获取电商数据的有效方法,力求在干货满满的同时,也不…

Linux系统网络的实时性评估

目录 1.使用 cyclictest 测试系统实时性2.测试系统通信实时性2.1 PingPlotter2.2 使用 ping 测试通讯实时性 3. 使用 iperf 测试带宽4.网络性能测试 1.使用 cyclictest 测试系统实时性 安装cyclictest sudo apt-get update sudo apt-get install rt-testscyclictest -p 99 -i…

代码第三十六天:需要添加的硬币的最小数量

需要添加的硬币的最小数量 题目要求: 解题思路 为方便描述,把 0 也算作可以得到的数。 假设现在得到了区间 [ 0 , s − 1 ] [0,s−1] [0,s−1] 中的所有整数,如果此时遍历到整数 x c o i n s [ i ] xcoins[i] xcoins[i],那么…

win10 安装kubectl,配置config连接k8s集群

安装kubectl 按照官方文档安装:https://kubernetes.io/docs/tasks/tools/install-kubectl-windows/ curl安装 (1)下载curl安装压缩包: curl for Windows (2)配置环境变量: 用户变量: Path变…

Python之Opencv教程(2):图像边缘检测

1、什么是边缘检测 OpenCV中的边缘检测是一种常见的图像处理技术,用于检测图像中物体边缘的位置。常用的边缘检测算法包括Sobel算子、Scharr算子、Laplacian算子和Canny边缘检测算法等。下面将介绍使用OpenCV实现这些边缘检测算法的方法。 2、边缘检测的作用 边缘…

STM32 字符数组结束符 “\0”

STM32 字符数组结束符 “\0” 使用字符数组使用printf,string参考 使用字符数组 使用STM32的串口发送数据,核心代码如下: char str[] "hello world!\n\r";while(1) {HAL_UART_Transmit(&huart2, str, sizeof (str), 10);HAL…

【力扣刷题日记】1173.即时食物配送I

前言 练习sql语句,所有题目来自于力扣(https://leetcode.cn/problemset/database/)的免费数据库练习题。 今日题目: 1173.即时食物配送I 表:Delivery 列名类型delivery_idintcustomer_idintorder_datedatecustomer…

Java学生管理系统(附完整代码)两个版本

目录 学生管理系统 需求: 分析: 初始菜单: 学生类: 添加功能: 删除功能: 修改功能: 查询功能: 设计图 学生管理系统(基础版)独立开发 所用方法 代码: Student类: Stud…

LabVIEW双通道太阳射电频谱观测系统

LabVIEW双通道太阳射电频谱观测系统 开发了一个基于LabVIEW平台开发的双通道高速太阳射电频谱观测系统。该系统实时监测太阳射电爆发,具有随机性、持续时间短、变化快等特点。通过高速信号采集卡实现1.5 GS/s的信号采集,时间分辨率可达4ms,频…

类的新功能

类的新功能 默认成员函数 在C11之前,一个类中有如下六个默认成员函数: 构造函数。拷贝构造函数赋值重载析构函数取地址重载函数const取地址函数 其中前四个默认成员函数最重要,后面两个默认成员函数一般不会用到,这里默认成员…

PHPCMS v9城市分站插件

PHPCMS自带的有多站点功能,但是用过的朋友都知道,自带的多站点功能有很多的不方便之处,例如站点栏目没法公用,每个站点都需要创建模型、每个站点都需要单独添加内容,还有站点必须静态化。如果你内容很多这些功能当然无…

虚函数和纯虚函数

虚函数 被virtual修饰的成员函数称为虚函数 定义一个函数为虚函数&#xff0c;是为了使用基类指针调用子类函数。虚函数&#xff0c;不代表函数不被实现。只有纯虚函数才不被实现&#xff0c;纯虚函数定义了一个接口&#xff0c;起到规范的作用。 #include <iostream>…

【AXIS】AXI-Stream FIFO设计实现(四)——异步时钟

前文介绍了几种同步时钟情况下的AXI Stream FIFO实现方式&#xff0c;一般来说&#xff0c;FIFO也需要承担异步时钟域模块间数据传输的功能&#xff0c;本文介绍异步AXIS FIFO的实现方式。 如前文所说&#xff0c;AXI-Stream FIFO十分类似于FWFT异步FIFO&#xff0c;推荐参考前…

B201-SpringBoot整合Shiro

目录 ShiroShiro核心组件SpringBoot整合Shiro1.创建新SpringBoot项目和导包2.自定义Shiro过滤器Realm3.配置类ShiroConfig编写认证和授权规则案例&#xff1a;案例思路改造ShiroConfigAccountController配置视图解析器templates下新建3个页面启动测试 登录认证设置自定义登录页…