首页 > 其他分享 >纯手写实现JDK动态代理

纯手写实现JDK动态代理

时间:2022-11-02 11:23:34浏览次数:41  
标签:JDK 代理 业务 Proxy 手写 动态 加载

前言

在Java领域,动态代理应用非常广泛,特别是流行的Spring/MyBatis等框架。JDK本身是有实现动态代理技术的,不过要求被代理的类必须实现接口,不过cglib对这一不足进行了有效补充。本篇博客将涉及2个话题:第一,JDK动态代理的实现原理,带你探索动态代理的实质面目;第二,自己动手写代码去实现JDK动态代理,去创造世界!

JDK动态代理

先写一个例子,感性认识下动态代理~

业务接口:

interface

业务实现类:

interface impl

业务处理类:

Handler

测试类:

test

运行结果:

result

在JDK动态代理中涉及如下角色:

业务接口Interface、业务实现类target、业务处理类Handler、JVM在内存中生成的动态代理类$Proxy0

动态代理原理图:

动态代理原理图

动态代理的真实面目

说白了,动态代理的过程是这样的:

第一:Proxy通过传递给它的参数(interfaces/invocationHandler)生成代理类$Proxy0;

第二:Proxy通过传递给它的参数(ClassLoader)来加载生成的代理类$Proxy0的字节码文件;

我们来看看上面例子中生成的$Proxy0的模样:

image

$Proxy0

**首先,$Proxy是实现了我们的业务接口(Man)的,所以客户端显然可以调用业务接口的方法。
**

其次,注意到$Proxy是继承自Proxy,并通过构造方法将业务处理类传入给父类Proxy进行初始化。(实质上,你可以看看源码,在Proxy中存在protected InvocationHandler h;)

初始化Proxy

初始化Proxy

findObject

**很明显,我们看到了业务接口的方法是如何被调用的:
**

最终都是回调业务处理类(具体的Handler)的invoke方法完成调用!

手写代码实现JDK动态代理

在上面,我们已经分析了JDK动态代理的整个调用过程,接下来,我们就来手写实现它吧!

先来看一眼图:

image

手写实现JDK动态代理

自定义InvocationHandler:

MyInvocationHandler

实现MyInvocationHandler的业务处理Handler:

MyHandler

自定义类加载器MyClassLoader:

MyClassLoader

为什么要定义一个自定义的类加载器呢?它的作用是什么呢?

要知道,我们是想手写JDK动态代理,那么我们将自己在内存中生成动态代理类,那么我们如何加载呢?这时候,就可以利用自定义的类加载器做到!

上述代码,重写了findClass方法,就是为了在指定路径下加载指定的字节码文件。

自定义MyProxy:

MyProxy

MyProxy的作用就相当于JDK的Proxy。MyProxy做了哪些事情呢?

第一:需要根据interfaces接口构造出动态代理类需要的方法。(其实就是利用反射获取)

第二:把动态生成的代理类(即.java文件)进行编译,生成字节码文件(即.class文件),然后利用类加载进行加载

第三:动态代理类进行加载后,利用反射机制,通过构造方法进行实例化,并在实例化时,初始化业务Hanlder

看一下MyProxy的其他方法:

编译方法
编译方法

getMethodString方法
getMethodString方法

运行结果
运行结果

我们来看一眼生成的$MyProxy0:

$MyProxy0

标签:JDK,代理,业务,Proxy,手写,动态,加载
From: https://www.cnblogs.com/little-monster-lhq/p/16850361.html

相关文章

  • JDK的安装与卸载
    卸载JDK1.删除java安装目录2.删除环境变量java_home3.删除path下关于java的目录4.cmd查看java-version命令安装JDK1.百度搜索JDK8下载安装2.环境变量中添加系统变量JAVA_......
  • JDK动态代理实现原理以及手写实现JDK动态代理
    JDK动态代理的过程JDK动态代理采用字节重组,重新生成对象来替代原始对象,以达到动态代理的目的。JDK中有一个规范,在ClassPath下只要是$开头的.class文件,一般都是自动生......
  • Centos离线安装JDK+Tomcat+MySQL8.0+Nginx
    一、安装JDK注:以下命令环境在Xshell中进行。1、查询出系统自带的OpenJDK及版本rpm-qa|grepjdk2、如果显示已安装openjdk则对其进行卸载。#卸载rpm-e--nodeps......
  • 动态代理
    动态代理主要需要理解,其实现是基于反射机制。代理模式当一个对象不能直接使用,可以在客户端和目标对象之间直接创建一个中介,这个中介就是代理。动态代理作用1、控制访......
  • 深度学习实战——numpy手写梯度下降法对价格进行预测
    导包准备importnumpyasnpimportpandasaspdimportjdcimportmatplotlib.pyplotaspltimportseabornassns#Visualization算法梯度求导公式对应的梯度计算,a代表学......
  • tensorflow keras从入门到精通——DcGAN生成手写数字
    导库fromkeras.modelsimportSequentialfromkeras.layersimportDense,BatchNormalizationfromkeras.layersimportReshapefromkeras.layers.coreimportActivatio......
  • 深度学习从入门到精通——pytorch实现生成手写数字
    网络构建该版本,网络全程采用全连接网络,激活函数采用leakyReLUfromtorchimportnnclassD_Net(nn.Module):def__init__(self):super().__init__()sel......
  • Jenkins Pipeline 流水线 - 添加节点 使用代理
    Jenkins安装在Windows上Docker在Linux上流程将Docker在Jenkins节点中维护Pipeline中指定某些阶段使用哪个节点添加节点CheckingJavaversionint......
  • 关于代理的设置
    环境变量设置代理全局设置代理就使用环境变量配置(这里只针对Linux或者Mac)vim/etc/profile--------------------------------------------http_proxy=IP:PORThttps_pr......
  • 使用HTTP代理IP需要了解的三个问题
    很多人都使用过HTTP代理IP,但有一些问题可能还不是很清楚,我们一起来看看吧。1、并非所有网站都可以访问很多朋友以为使用了HTTP代理IP,就可以访问所有的网站。事......