java JDK 动态代理(如何使用,以及工作原理解析)

freeswitch之呼叫中心acd模块开发 一、定义: ACD(Automatic Call Distributor) 自动呼叫分配,也叫智能选择座席。它是呼叫中心整个前台接入系统逻辑功能的描述:把接入的呼叫转接到正确的座席员桌前。ACD是现代呼叫中心有别于一般的热线电话系统和自动应答系统的重要标志,其性能的优劣直接影响到呼叫中心的效率和顾客的满意度。 二、ACD包含的功能点: 1 、程控交换功能 ACD在本质上也是交换机的一种类型,必须具有程控交换最基本的话务交换功能。 2 、排队功能 ACD必须具有话务排队的功能,所谓排队是指在内线都 阅读详情

JDK 动态代理如何使用

1:实现 InvocationHandler 接口
2:有一个自己定义的接口,名称为 InterFace。有一个实现InterFace接口的实现类。
3:使用 Proxy 中的 newProxyInstance 方法创建代理类。

具体的实现是请看下面的代码

被代理接口
package com.javaproxy.test;

public interface InterFace {

    public String interFaceMethod(String str);

}

被代理接口实现类
package com.javaproxy.test;

public class InterFaceImpl implements InterFace{

    @Override
    public String interFaceMethod(String str) {
        return str + "+lp";
    }

}

InvocationHandler接口实现类
package com.javaproxy.test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class InvocationHandlerImpl implements InvocationHandler {

    //要代理的原始对象
    private Object obj;

    public InvocationHandlerImpl(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("执行被代理方法前,需要做的处理doBefore");
        System.out.println("执行被代理方法 ing");
        Object result = method.invoke(obj, args);
        System.out.println("执行被代理方法后,需要做的处理doAfter");
        return result;
    }

}

测试类
package com.javaproxy.test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class TestJavaProxy {

    public static void main(String[] args) {
        InterFace impl = new InterFaceImpl();
        InvocationHandler handler = new InvocationHandlerImpl(impl);
        Object proxyObj= Proxy.newProxyInstance(impl.getClass().getClassLoader(), impl.getClass().getInterfaces(), handler);
        InterFace inter = (InterFace) proxyObj;
        inter.interFaceMethod("lp");
    }

}

运行测试类,结果
执行被代理方法前,需要做的处理doBefore
执行被代理方法 ing
执行被代理方法后,需要做的处理doAfter

JDK动态代理原理解析

JDK提供了sun.misc.ProxyGenerator.generateProxyClass(String proxyName,class[] interfaces) 底层方法来产生动态代理类的字节码:
下面定义了一个工具类,用来将生成的动态代理类保存到硬盘中:

package com.javaproxy.test;

import java.io.FileOutputStream;
import java.io.IOException;
import sun.misc.ProxyGenerator;

public class ProxyUtils {

    /*
     * 将根据类信息 动态生成的二进制字节码保存到硬盘中,
     * 默认保存到 D 盘根目录下
     * clazz 需要生成动态代理类的类
     * proxyName : 为动态生成的代理类的名称
     */
    public static void generateClassFile(Class<?> clazz, String proxyName) {
        // 根据类信息和提供的代理类名称,生成字节码
        byte[] classFile = ProxyGenerator.generateProxyClass(proxyName, clazz.getInterfaces());
        // String paths = clazz.getResource(".").getPath();
        String paths = "D:/";
        FileOutputStream out = null;

        try {
            // 保留到硬盘中
            out = new FileOutputStream(paths + proxyName + ".class");
            out.write(classFile);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

在测试类TestJavaProxy 中的main方法中的 Proxy.newProxyInstance代码下面添加代码 ProxyUtils.generateClassFile(proxyObj.getClass(), "ProxyObj");
这样就可以在,D盘的根目录下,找到 ProxyObj.class 文件,使用jd-gui 反编译工具打开。反编译后,代码如下。

import com.javaproxy.test.InterFace;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class ProxyObj extends Proxy
  implements InterFace
{
  private static Method m1;
  private static Method m0;
  private static Method m3;
  private static Method m2;

  public ProxyObj(InvocationHandler paramInvocationHandler)
    throws 
  {
    super(paramInvocationHandler);
  }

  public final boolean equals(Object paramObject)
    throws 
  {
    try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final int hashCode()
    throws 
  {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final String interFaceMethod(String paramString)
    throws 
  {
    try
    {
      return (String)this.h.invoke(this, m3, new Object[] { paramString });
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final String toString()
    throws 
  {
    try
    {
      return (String)this.h.invoke(this, m2, null);
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  static
  {
    try
    {
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      m3 = Class.forName("com.javaproxy.test.InterFace").getMethod("interFaceMethod", new Class[] { Class.forName("java.lang.String") });
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }
}

可以看到 通过 java.lang.reflect.Proxy 的方法 newProxyInstance 获取的代理类(ProxyObj),实现了,自己定义的 InterFace接口。所以在测试类里面,可以将 获取的代理类(ProxyObj)强制转换为InterFace对象类型。

再看 获取的代理类(ProxyObj),是如何调用被代理对象的,以及如何调用InvocationHandler接口实现类的。

代理类调用过程
1:获取的代理类强制转换为InterFace对象类型,调用 interFaceMethod 方法。
实际调用的方法 是 类ProxyObj 里面的interFaceMethod方法。
2:那么接着看,类ProxyObj 里面的interFaceMethod方法,方法内的代码是
try
{
return (String)this.h.invoke(this, m3, new Object[] { paramString });
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}

方法内,调用了代理类自己的属性 h(从java.lang.reflect.Proxy 继承过来的) 即咱们自己的InvocationHandler 接口的实现类InvocationHandlerImpl,然后调用, h 的 invoke方法。看看 invoke方法的参数,第一个参数传入进入的是代理对象自己,第二参数是静态代码初始化的Method对象
m3 = Class.forName("com.javaproxy.test.InterFace").getMethod("interFaceMethod", new Class[] { Class.forName("java.lang.String") });
第三个参数是,调用代理类对象中的方法是传递进来的参数。

讲到这里大家应该可以理解JDK的动态代理是怎么实现的了。

这个再贴一篇文章的地址,点击打开

接口调试必看:status显示canceled的3种常见原因及修复方法 本文深度解析了接口调试中status显示canceled的三种核心原因:网络层中断(如请求超时)、应用层逻辑主动取消(如请求竞态、组件卸载)以及用户交互与浏览器行为。文章提供了从诊断到修复的系统性方案,包括分析Network Timing、使用Axios CancelToken、优化请求策略与性能,帮助开发者从根本上解决这一常见问题。 阅读详情

相关推荐

从零搭建自动驾驶仿真环境:我的Nuplan-devkit实战笔记(含PyCharm配置技巧)

本文详细记录了从零搭建Nuplan-devkit自动驾驶仿真环境的完整流程,包括conda环境配置、pip版本控制、PyCharm专业版集成等关键步骤。特别针对Ubuntu系统下的依赖管理、数据目录优化和性能调优提供了实用技巧,帮助开发者高效构建稳定的自动驾驶仿真开发环境。

weixin_30505225的博客 480

JDK的动态代理

主要就一句: Proxy.newProxyInstance(a,b,c) a参数是自己的类,b参数是要实现加强类的接口,c参数是自己写的加强类,要自己写,继承 InvocationHandler接口 这句执行完即可获得加强类 package com.dao; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public c.

sharesb的博客 565

【机器人】线性方程最小二乘解法对机械臂DH参数进行标定

1.前言 看了一篇文章,觉得里面的DH参数标定法讲的很清晰,便使用Matlab复现了一下,效果还可以,特写此文记录。 2.原理 2.1.误差最佳值的最小二乘计算 有研究结果表明:几乎95%的机器人位置误差都是由机器人内部运动学的不准确描述引起的,所以对DH模型参数进行标定是很有必要的。 DH参数物理含义:选自《机器人学、机器视觉与控制-Matlab基础》 当DH参数确定后,我们...

要恰饭得嘛 1万+

【面试精讲】Java动态代理是如何实现的?JDK Proxy 和 CGLib 有什么区别?

本文深入探讨了Java动态代理的实现机制,分别介绍了使用JDK Proxy和CGLib两种不同方式来实现动态代理。

小明的Java问道之路 5138

STM32铅酸蓄电池内阻测试仪的交流阻抗测量与数据采集优化

本文深入探讨了基于STM32的铅酸蓄电池内阻测试仪设计,重点解析了交流阻抗测量原理与数据采集优化方案。通过采用1kHz交流小信号注入和数字相敏检波技术,实现对电池欧姆内阻的无损精准测量,并详细介绍了硬件前端调理、ADC过采样及系统标定等关键优化手段,有效提升了测量精度与稳定性。

weixin_29168393的博客 487

Abaqus边界条件设置避坑指南:为什么你的实体单元转动自由度总是不生效?

本文深入解析了Abaqus中实体单元转动自由度设置失效的根本原因。从力学原理与有限元节点自由度的本质区别出发,阐明了实体单元仅具有平动自由度,直接约束其转动自由度是无效操作。文章提供了对称边界条件的正确设置方法,并给出了使用耦合约束等高级方案来模拟真实抗转动约束的实战指南,帮助用户避免常见建模陷阱。

weixin_29290379的博客 622

Java:JDK如何创建动态代理Proxy

动态代理是Java编程语言中的一种特性,允许在运行时创建代理类和对象。它主要用于实现AOP(面向切面编程)和在运行时处理其他类的方法调用,例如远程方法调用(RPC)、事务管理等。

Cosmoshhhyyy的博客 431

手把手教你用8位单片机IO口直接驱动WS2812灯带(附完整代码和避坑指南)

本文详细介绍了如何使用8位单片机IO口直接驱动WS2812灯带,包括硬件准备、时序生成、色彩引擎与特效算法的实现,以及调试技巧与性能优化。通过汇编语言优化和精确时序控制,实现高效的LED驱动和炫酷的彩虹灯效,适合嵌入式开发者和硬件爱好者参考。

weixin_42696271的博客 304

Java动态代理[JDK Proxy]

要给这个方法去增加其他的功能只能把这两段代码都写在eat方法当中,那此时直接去修改代码,是叫做侵入式修改。代理会帮你先去做拿筷子和盛饭这两个准备工作,等真正的吃饭了再去调用Student里面的方法去吃饭,这个呢其实就是动态代理。1.为什么需要代理呢?

weixin_53622554的博客 944

conda upgrade出现Solving environment:failed CondaValueError Malformed version string invalid chars解决方案

本文主要介绍了conda install出现Solving environment:failed、CondaValueError: Malformed version string invalid character(s),希望能对使用conda的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案 2.1 步骤一 2.2 步骤二

weixin_43178406的博客 8万+

【Docker】一招解决超时镜像超时报错:`ERROR: Get https://registry-1.docker.io/v2/`

Docker 镜像拉取超时或失败并不是 Docker 本身的缺陷,而是网络环境和默认配置在特定场景下的限制所导致的结果。通过本文的分析可以看到,问题的核心往往集中在三个方面:网络访问延迟、DNS 解析速度以及客户端默认超时时间。针对这些问题,最直接、有效的做法是使用国内镜像加速器,这不仅能够显著提升拉取速度,还能保证在企业内网或家庭网络中更加稳定

博客 1029

代理

什么是代理: 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式; 即通过代理访问目标对象。代理的好处:是可以在目标对象实现的基础上, 增强额外的功能操作,(扩展目标对象的功能)。代理模式的关键点;代理对象与目标对象。 类型: 1静态代理 静态代理是指程序运行前就已经存在了代理类的字节码文件, 代理类和代理类的关系在运行前就已经确定, 特点:1.可以在不修改目标对象的功能前提下,对目...

qq_43254623的博客 302

AUTOSAR汽车电子嵌入式编程精讲300篇-基于加密算法的车载CAN总线安全通信

随着科学技术的不断更新和社会文明的不断进步,汽车已经走入寻常百姓家, 成为当代社会必不可少的交通工具。伴随着互联网技术的飞速发展,汽车也不再 是一个简单的交通工具,已经逐渐发展成为一个集出行、通信、娱乐等功能于一 身的综合智能体,进而推动了车联网产业的蓬勃发展。车联网是在传统汽车的框架上安装了传感器、执行器、控制器等分布式和集 中式控制器,使汽车具备环境感知、协同控制、优化执行等功能,并通过网络技 术实现与车外环境的信息共享,给驾驶带来方便的同时也终将成为可以替代人操 作的新一代汽车[1-3]。

getusushu的博客 2591

jdk动态代理和cglib动态代理的原理分析

文章目录一、基本代理知识了解①静态代理②jdk动态代理③cglib动态代理二.jdk动态代理和cglib动态代理的共同点?三.jdk动态代理是怎么生成代理对象的? 本文解决一下几个问题: 1.jdk动态代理和cglib动态代理的共同点? 2.jdk动态代理是怎么生成代理对象的? 3.cglib是怎么生成代理对象的? 4.jdk和cglib各自怎么调用被代理对象的方法? 5.cglib动态生成的代理对象的时候为什么是3个class? 一、基本代理知识了解 ①静态代理 静态代理是设计模式中规范的模式。 来个

baidu_21349635的专栏 1693

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

jdk动态代理与cglib动态代理

java中的动态代理主要分为两种方式:1.jdk动态代理;2.cglib动态代理 1. jdk动态代理 //首先创建一个接口 public interface Hello { String sayhello(String str); } //该类实现Hello接口作为被代理的类 public class HelloImpl implements Hello{ public St...

jwnba24的博客 441

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

基于jdk动态代理的实现与源码解析

Java有动态代理本质就是借助Java的字节码操作工具来实现在Java程序运行的时候动态生成相关的新的字节码,即新的类,并用新生成的类的对象实现相关额外操作 动态代理在spring框架中被广泛地使用,主要有两种动态代理,一种是基于JDK本身的,别一种是基于cglib的,在spring中,如果一个类实现了某个接口,就用Jdk动态代理 来实现,如果没有实现任何相关的接口,就用cglib来实

tiandesheng111的专栏 699

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

谁与争锋,JDK动态代理大战CGLib动态代理

文章目录一、前言二、基本概念三、JDK 和 CGLib动态代理区别3.1 JDK动态代理具体实现原理3.2 CGLib动态代理3.3 两者对比3.4 使用注意四、JDK 和 CGLib动态代理性能对比-教科书上的描述五、使用层面:性能测试 + 模拟JDK动态代理 + 模拟Cglib动态代理六、原理层面:Fastclass机制6.1 cglib代理使用Fastclass机制七、面试金手指7.0 三种代理方式和两种动态代理方式7.1 jdk动态代理和cglib动态代理7.1.1 jdk动态代理和cglib动态代

毛毛的专栏 3122

JDK 动态代理和 CGLIB 动态代理

通过反编译生成的 JDK 代理类和 CGLIB 代理类,我们可以看到它们两种不同机制的实现: JDK 动态代理是通过实现目标类的接口,然后将目标类在构造动态代理时作为参数传入,使代理对象持有目标对象,再通过代理对象的 InvocationHandler 实现动态代理的操作。CGLIB 动态代理是通过配置目标类信息,然后利用 ASM 字节码框架进行生成目标类的子类。当调用代理方法时,通过拦截方法的方式实现代理的操作。总的来说,JDK 动态代理利用接口实现代理,CGLIB 动态代理利用继承的方式实现代理。

lonelyhiker 364

invocationhandler接口_jdk动态代理为什么要使用接口,而不是使用继承

最近面试当时问到了Spring AOP的实现方式,然后就问到了jdk动态代理为什么使用接口而不是使用继承,当时一时没转过弯来,后来自己回来看了一下原来如此,面试有时就是这样问题不难,但就是可能想不到这个点去回答。分析动态代理是使用反射和字节码的技术,在运行期创建指定接口和类的子类以及其实例对象的技术,通过动态代理可以对代码进行增强。java动态代理主要有两种形式:JDK原生的动态代理和CGLIB动...

weixin_32349577的博客 1355

Java反射——Proxy和动态代理

概述 上篇文章《Java反射——Class和ClassLoader 》,我们简单介绍了反射的基本概念及相关类。这里介绍下,反射的一个主要应用——动态代理。 动态代理 JDK CGLIB API 小结 ...

技术交流 769

Spring中两种动态代理:JDK动态代理和CGLib动态代理

基本概念 自Java 1.3以后,Java提供了动态代理技术,允许开发者在运行期创建接口的代理实例,后来这项技术被用到了Spring的很多地方。 JDK动态代理主要涉及java.lang.reflect包下边的两个类:Proxy和InvocationHandler。其中,InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态地将横...

程铭程铭你快成名的博客 1967

jdk 动态代理的原理

一、代理设计模式 代理设计模式是Java常用的设计模式之一。 特点: 01.委托类和代理类有共同的接口或者父类; 02.代理类负责为委托类处理消息,并将消息转发给委托类; 03.委托类和代理类对象通常存在关联关系,一个代理类对象与一个委托类对象关联; 04.代理类本身不是真正的实现者,而是通过调用委托类方法来实现代理功能; 二、静态代理与动态代理 按照代理类创建的时机,代理类分为两...

weixin_34402408的博客 184

Java动态代理的实现方式

代理模式是一种设计模式,,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,。代理分为动态代理和静态代理。举例:通过中介进行的商品交易,中介就是代理,代替卖方进行商品销售。静态代理比较麻烦,需要对每个目标对象都设置专用的代理类,实际开发中很少使用。动态代理是的一种技术。**从 JVM 角度来说,动态代理是在运行时动态生成类字节码,并加载到 JVM 中的。

Mr_Richard的博客 1896

JDK 动态代理 vs CGLIB 动态代理:一文搞懂两种动态代理技术

摘要 本文介绍了Java中两种动态代理技术:JDK动态代理和CGLIB动态代理。JDK动态代理基于接口实现,通过反射机制生成代理对象,适用于有接口的类;CGLIB则通过继承目标类并重写方法实现代理,不依赖接口。JDK动态代理使用简单但性能较低,而CGLIB性能更高但对final类/方法无效。两种技术各有优劣,开发者可根据项目需求选择合适的代理方式。动态代理广泛应用于AOP编程、框架设计等领域,是Java开发中的重要技术。

深耕后端、偏爱架构,用代码与设计构建可靠系统 1049

分析为什么java动态代理是基于接口

前言 最近一直在研究Spring的源码,就看到了一些有关Java动态代理的博客。发现有些针对Java原生动态代理的博客没有写的很详细,不少都是一知半解互相粘贴的。所以写了一个小东西去研究,就诞生了这篇博客。希望对大家理解动态代理有一个新的帮助。 从一个异常开始 我们先把问题提出来,比如我有以下的代码。一个接口Dao,一个实现类DemoDao,一个切面类用来产生代理的 MyAspect,一个测试类MainTest。 public interface Dao { void print(); } @Re

Smallc0de的博客 576

聊聊JDK中Proxy、InvocationHandler的使用以及动态代理

对于熟悉设计模式的宝宝们来说,代理模式的应用场景在生活中随处可见,JDK中的用例也比比皆是(Thread类&Runnable接口的设计)。这种模式的本意在于控制对被代理对象(目标对象)的访问,但在实际运用中可以实现各种复杂的业务逻辑(如记录log,性能分析。。。)。 根据代理类的不同分为静态和动态代理,静态代理需要在程序中手动产生代理类并加入业务逻辑。这种方式虽然客户端操作复杂,但实现起来相对容

陈老师的专栏 841
上一篇: java中==与equel的区别
下一篇: spring AOP 基于注解(spring版本4.2.0)
三易的博客
博客等级 码龄15年 42粉丝 89原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值