返回顶部
首页 > 资讯 > 后端开发 > Python >详解Java Proxy动态代理机制
  • 315
分享到

详解Java Proxy动态代理机制

2024-04-02 19:04:59 315人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

一、JVM加载对象 在说Java动态代理之前,还是要说一下Jvm加载对象的过程,这个依旧是理解动态代理的基础性原理: Java类即源代码程序.java类型文件,经过编译器编译之后就

一、JVM加载对象

在说Java动态代理之前,还是要说一下Jvm加载对象的过程,这个依旧是理解动态代理的基础性原理:

Java类即源代码程序.java类型文件,经过编译器编译之后就被转换成字节代码.class类型文件,类加载器负责读取字节代码,并转换成java.lang.Class对象,描述类在元数据空间的数据结构,类被实例化时,堆中存储实例化的对象信息,并且通过对象类型数据的指针找到类。

过程描述:源码->.java文件->.class文件->Class对象->实例对象

所以通过New创建对象,独断其背后很多实现细节,理解上述过程之后,再了解一个常用的设计模式,即代理模式。

二、代理模式

1、基本描述

代理模式给某一个(目标)对象提供一个代理对象,并由代理对象持有目标对象的引用。所谓代理,就是一个对象代表另一个对象执行相应的动作程序。而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式在实际的生活中场景很多,例如中介、律师、代购等行业,都是简单的代理逻辑,在这个模式下存在两个关键角色:

目标对象角色:即代理对象所代表的对象。

代理对象角色:内部含有目标对象的引用,可以操作目标对象;aop编程就是基于这个思想。

2、静动态模式

  • 静态代理:在程序运行之前确定代理角色,并且明确代理类和目标类的关系。
  • 动态代理:基于Java反射机制,在JVM运行时动态创建和生成代理对象。

三、静态代理

基于上述静态代理的概念,用一段代码进行描述实现,基本逻辑如下:

  • 明确目标对象即被代理的对象;
  • 定义代理对象,通过构造器持有目标对象;
  • 代理对象中定义前后置增强方法;

目标对象与前后置增强代码就组成了代理对象,这样就不用直接访问目标对象,像极了电视剧中那句话:我是律师,我的当事人不方便和你对话。


public class Proxy01 {
    public static void main(String[] args) {
        TargetObj targetObj = new TargetObj() ;
        ProxyObj proxyObj = new ProxyObj(targetObj) ;
        proxyObj.invoke();
    }
}
class TargetObj {
    public void execute (){
        System.out.println("目标类方法执行...");
    }
}
class ProxyObj {
    private TargetObj targetObj ;
    
    public ProxyObj (TargetObj targetObj){
        this.targetObj = targetObj ;
    }
    
    public void invoke (){
        before () ;
        targetObj.execute();
        after () ;
    }
    
    public void before (){
        System.out.println("代理对象前置处理...");
    }
    public void after (){
        System.out.println("代理对象后置处理...");
    }
}

静态代理明确定义了代理对象,即有一个代理对象的.java文件加载到JVM的过程,很显然的一个问题,在实际的开发过程中,不可能为每个目标对象都定义一个代理类,同样也不能让一个代理对象去代理多个目标对象,这两种方式的维护成本都极高。

代理模式的本质是在目标对象的方法前后置入增强操作,但是又不想修改目标类,通过前面反射机制可以知道,在运行的时候可以获取对象的结构信息,基于Class信息去动态创建代理对象,这就是动态代理机制。

顺便说一句:技术的底层实现逻辑不好理解是众所周知,然而基础知识点并不复杂,例如代理模式的基本原理,但是结合到实际的复杂应用中(AOP模式),很难活灵活现的理解到是基于反射和动态代理的方式实现的。

四、动态代理

1、场景描述

基于一个场景来描述动态代理和静态代理的区别,即最近几年很火的概念,海外代购:

在代购刚兴起的初期,是一些常去海外出差的人,会接代购需求,即代理人固定;后来就兴起海外代购平台,海淘等一系列产品,即用户代购需求(目标对象)由代购平台去实现,但是具体谁来操作这个就看即时分配,这个场景与动态代理的原理类似。

2、基础API案例

首先看两个核心类,这里简述下概念,看完基本过程再细聊:

Proxy-创建代理对象,核心参数:

  • ClassLoader:(目标类)加载器;
  • Interfaces:(目标类)接口数组
  • InvocationHandler:代理调用机制;

InvocationHandler-代理类调用机制:

  • invoke:这个上篇说的反射原理;
  • method:反射类库中的核心api

目标对象和接口


interface IUser {
    Integer update (String name) ;
}
class UserService implements IUser {
    @Override
    public Integer update(String name) {
        Integer userId = 99 ;
        System.out.println("UserId="+userId+";updateName="+name);
        return userId ;
    }
}

代理对象执行机制


class UserHandler implements InvocationHandler {
    private Object target ;
    public UserHandler (Object target){
        this.target = target ;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before()...");
        Object result = method.invoke(target, args);
        System.out.println("after()...");
        return result;
    }
}

具体组合方式


public class Proxy02 {
    public static void main(String[] args) {
        
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        
        IUser userService = new UserService();
        ClassLoader classLoader = userService.getClass().getClassLoader();
        Class<?>[] interfaces = UserService.class.getInterfaces() ;
        
        InvocationHandler userHandler = new UserHandler(userService);
        
        String proxyClassName = Proxy.newProxyInstance(classLoader,interfaces,userHandler).getClass().getName();
        System.out.println("proxyClassName="+proxyClassName);
        
        IUser proxyUser1 = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);
        IUser proxyUser2 = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);
        proxyUser1.update("cicada") ;
        proxyUser2.update("smile") ;
    }
}

这里之所以要生成代理类的结构信息,因为从JVM加载的过程看不到相关内容,关键信息再次被独断:


javap -v Proxy02.class

查看代理类名称



String proxyClassName = Proxy.newProxyInstance(classLoader,interfaces,userHandler).getClass().getName();
System.out.println("proxyClassName="+proxyClassName);

下意识输出代理对象名称,这里即对应JVM机制,找到Class对象名,然后分析结构,这样就明白动态代理具体的执行原理了。

生成代理类.class文件


System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

通过上面JVM加载对象的机制可知,描述代理类的Class对象一定存在,只是在运行时并没有生成显式的.class文件,通过上面生成代理类.class的语法,会在项目目录的/com/java/proxy路径下创建文件。

顺便说一句:作为一只程序员,复杂总是和我们环环相绕,说好的简单点呢?

3、代理类结构

继承与实现


class $Proxy0 extends Proxy implements IUser {}

从代理类的功能来思考,可以想到需要继承Proxy与实现IUser接口,还有就是持有调用机制的具体实现类,用来做业务增强。

构造方法


public $Proxy0(InvocationHandler var1) throws  {
    super(var1);
}

通过构造方法,持有UserHandler具体的执行机制对象。

接口实现


final class $Proxy0 extends Proxy implements IUser {
    private static Method m3;
    public final Integer update(String var1) throws  {
        try {
            return (Integer)super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }
}

目标类的基本需求update()方法,通过代理类进行承接,并基于UserHandler实现具体的增强业务处理。

基础方法


final class $Proxy0 extends Proxy implements IUser {
    private static Method m0;
    private static Method m1;
    private static Method m2;
    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }
    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.java.proxy.IUser").getMethod("update", Class.forName("java.lang.String"));
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
    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 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 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);
        }
    }
}

基于Object类,定义Java中几个常用方法equals()判断,toString()方法,hashCode()值,这个在分析Map源码的时候有说过为什么这几个方法通常都是一起出现。

4、JDK源码

上面是案例执行的过程和原理,还有一个关键点要明白,即jdk源码的逻辑:


IUser proxyUser = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);

Proxy提供的静态方法newProxyInstance(),通过各个参数的传入,构建一个新的代理Class对象,即$Proxy0类的结构信息,这里再回首看下三个核心参数:

  • ClassLoader:基于JVM运行过程,所以需要获取目标类UserService的类加载器;
  • Interfaces:目标类UserService实现的接口,从面向对象来考虑,接口与实现分离,代理类通过实现IUser接口,模拟目标类的需求;
  • InvocationHandler:代理类提供的功能封装即UserHandler,可以在目标方法调用前后做增强处理;

最后总结一下动态代理的实现的核心技术点:Jvm加载原理、反射机制、面向对象思想;每次阅读JDK的源码都会惊叹设计者的鬼斧神工,滴水穿石坚持才会有收获。

JVM类加载机制 | 代理模式 | AOP切面编程 | 自定义日志记录 | Map源码分析

五、源代码地址

GitHub·地址https://github.com/cicadasmile/java-base-parent

GitEE·地址Https://gitee.com/cicadasmile/java-base-parent

到此这篇关于详解Java动态代理机制的文章就介绍到这了,更多相关Java动态代理内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 详解Java Proxy动态代理机制

本文链接: https://lsjlt.com/news/129246.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 详解Java Proxy动态代理机制
    一、Jvm加载对象 在说Java动态代理之前,还是要说一下Jvm加载对象的过程,这个依旧是理解动态代理的基础性原理: Java类即源代码程序.java类型文件,经过编译器编译之后就...
    99+
    2024-04-02
  • 详解Java的Proxy动态代理机制
    目录一、Jvm加载对象二、代理模式2.1、基本描述2.2、静动态模式三、静态代理四、动态代理4.1、场景描述4.2、基础API案例4.3、代理类结构4.4、JDK源码五、源代码地址一...
    99+
    2024-04-02
  • Java动态代理机制的实例详解
     Java动态代理机制在学习spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功...
    99+
    2023-05-31
    java 动态代理 ava
  • 详解Java中的反射机制和动态代理
    目录一、反射概述二、反射之Class类2.1、初识Class类2.2、Class有下面的几个特点2.3、获取Class类实例2.4、关于包装类的静态属性2.5、通过Class类的其他...
    99+
    2024-04-02
  • java proxy动态代理怎么实现
    在Java中,可以通过使用`java.lang.reflect.Proxy`类来实现动态代理。首先,需要定义一个接口,代表被代理类和...
    99+
    2023-09-09
    java
  • Java Proxy机制详细解读
     动态代理其实就是java.lang.reflect.Proxy类动态的根据您指定的所有接口生成一个class byte,该class会继承Proxy类,并实现所有你指定的接口(您在参数中传入的接口数组);然后再利用您指定的cla...
    99+
    2023-05-31
    java proxy机制 rox
  • JAVA代理,静态,动态详解
    目录代理静态代理动态代理JDK动态代理CGLib动态代理总结代理 为其他对象提供一种代理以控制这个对象的访问,在某些情况下一个对象不能直接访问那个对象时,代理就起到了客户端和被代理对...
    99+
    2024-04-02
  • Java CGLib动态代理机制(全面解析)
    一、首先说一下JDK中的动态代理:JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接口实现的但是,JDK中所要进行动态代理的类必须要实现一个接口,也就是说只能对该类所实现接口中定义的方法进行代理,这在实际编...
    99+
    2023-05-31
    java 动态代理 cglib
  • JAVA的动态代理详解
    文章目录 前言一、动态是什么?二、使用步骤1.导入相应的包2.定义接口3.定义接口实现类4.实现InvocationHandler接口5.实现代理 三、整体实例四、输出结果总结 前言...
    99+
    2023-08-31
    java 开发语言
  • java jdk动态代理详解
    jdk动态代理要对一个类进行代理,被代理的类必须实现至少一个接口,并且只有接口中的方法才能被代理。 jdk实现动态代理一般分为三步: 1. 编写接口和实现类。 2. 写一个处理器,该...
    99+
    2022-11-15
    java jdk 动态代理
  • Java动态代理机制是什么
    这篇文章主要讲解了“Java动态代理机制是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java动态代理机制是什么”吧!Java动态代理机制的出现,使得Java开发人员不用手工编写代理类...
    99+
    2023-06-17
  • 关于Java的动态代理机制
    目录静态代理功能接口功能提供者功能代理者探索动态代理实现机制静态代理 常规的代理模式有以下三个部分组成: 功能接口 interface IFunction { void doATh...
    99+
    2023-05-19
    Java 代理 Java 动态代理
  • Java的动态代理和静态代理详解
    目录0、代理模式1、静态代理2、 加深理解3、动态代理动态代理的例子总结0、代理模式 为什么要学习代理模式?这是SpringAOP的底层【SpringAOP和SpringMVC】 代...
    99+
    2024-04-02
  • Java 动态代理中Proxy的使用方法
    本篇文章给大家分享的是有关Java 动态代理中Proxy的使用方法,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实...
    99+
    2023-06-17
  • Java静态代理与动态代理案例详解
    代理模式 代理模式(Proxy):为其他对象提供一个代理以控制对这个对象的访问。 主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象...
    99+
    2024-04-02
  • 详解java 中的动态代理
    这期内容当中小编将会给大家带来有关详解java 中的动态代理,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Java动态代理相关先来看静态代理模式代码:package test; public inter...
    99+
    2023-05-31
    java 动态代理 ava
  • Java动态代理的示例详解
    目录定义分类案例需求方案一:jdk动态代理方案二:cglib动态代理分析总结定义 动态代理指的是,代理类和目标类的关系在程序运行的时候确定的,客户通过代理类来调用目标对象的方法,是在...
    99+
    2024-04-02
  • jdk动态代理和cglib动态代理详解
    目录静态代理基于继承的方式实现静态代理基于聚合的方式实现静态代理继承与聚合方式实现的静态代理对比动态代理JDK动态代理如何实现一个HashMap的动态代理类?Cglib动态代理JDK...
    99+
    2024-04-02
  • Java中动态代理机制的原理是什么
    今天就跟大家聊聊有关Java中动态代理机制的原理是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Java 动态代理机制的出现,使得 Java  开发人员不用手工编写代理...
    99+
    2023-06-17
  • 从另一个角度理解Java中的动态代理机制
    本篇文章为大家展示了从另一个角度理解Java中的动态代理机制,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。class文件简介及加载Java编译器编译好Java文件之后,产生.class 文件在磁盘中...
    99+
    2023-05-31
    java 动态代理 ava
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作