当前位置: 首页 > wzjs >正文

虚拟主机怎么设计网站吗青海seo关键词排名优化工具

虚拟主机怎么设计网站吗,青海seo关键词排名优化工具,wordpress免费采集,asp网站建设教程文章目录一、动态代理的本质二、核心实现机制1. 核心类与职责2. 代理对象创建流程三、完整实践示例解析四、代理类结构解析四、方法调用全流程六、关键特性与限制总结摘要:本文深入剖析JDK动态代理的实现机制,结合字节码生成与调用转发原理,揭…

文章目录

    • 一、动态代理的本质
    • 二、核心实现机制
      • 1. 核心类与职责
      • 2. 代理对象创建流程
    • 三、完整实践示例解析
    • 四、代理类结构解析
    • 四、方法调用全流程
    • 六、关键特性与限制
    • 总结

摘要:本文深入剖析JDK动态代理的实现机制,结合字节码生成与调用转发原理,揭示其如何成为Spring等框架的AOP基石。

前面看Spring AOP的源码,所以对于 JDK 动态代理具体是如何实现的产生了兴趣,想着从源码上了解这个原理的话,也有助于对 spring-aop 模块的理解;


JDK 动态代理其实是 Java 标准库提供的基于接口的代理实现,其核心原理可概括为 运行时动态生成代理类字节码 + 方法调用转发。以下是详细解析:

一、动态代理的本质

动态代理是一种运行时生成代理对象的技术,无需手动编写代理类。JDK动态代理是Java标准库提供的原生方案,其核心能力:

  • 接口代理:仅支持基于接口的代理
  • 无侵入扩展:在方法调用前后插入自定义逻辑(如日志、事务)
  • 运行时字节码生成:动态创建代理类的.class文件

🌟 典型场景:Spring的@Transactional事务管理、MyBatis的Mapper接口实现

二、核心实现机制

1. 核心类与职责

类/接口职责
java.lang.reflect.Proxy入口类,提供newProxyInstance()创建代理对象
InvocationHandler调用处理器,所有代理方法调用均转发到其invoke()方法
ProxyGenerator (内部)动态生成代理类字节码(JDK内部类)

2. 代理对象创建流程

// Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
// 创建代理对象的核心代码
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException
{Objects.requireNonNull(h);final Class<?>[] intfs = interfaces.clone();final SecurityManager sm = System.getSecurityManager();if (sm != null) {checkProxyAccess(Reflection.getCallerClass(), loader, intfs);}/** Look up or generate the designated proxy class.*/// 1. 动态生成代理类字节码Class<?> cl = getProxyClass0(loader, intfs);/** Invoke its constructor with the designated invocation handler.*/try {if (sm != null) {checkNewProxyPermission(Reflection.getCallerClass(), cl);}// 2. 获取构造器并实例化final Constructor<?> cons = cl.getConstructor(constructorParams);final InvocationHandler ih = h;if (!Modifier.isPublic(cl.getModifiers())) {AccessController.doPrivileged(new PrivilegedAction<Void>() {public Void run() {cons.setAccessible(true);return null;}});}return cons.newInstance(new Object[]{h});} catch (IllegalAccessException|InstantiationException e) {throw new InternalError(e.toString(), e);} catch (InvocationTargetException e) {Throwable t = e.getCause();if (t instanceof RuntimeException) {throw (RuntimeException) t;} else {throw new InternalError(t.toString(), t);}} catch (NoSuchMethodException e) {throw new InternalError(e.toString(), e);}
}

关键步骤:

  1. 根据接口数组生成代理类字节码(如$Proxy0.class
  2. 通过类加载器加载字节码
  3. 反射构造代理对象,绑定InvocationHandler

三、完整实践示例解析

一般会使用实现了 InvocationHandler接口 的类作为代理对象的生产工厂类,并且通过持有被代理对象target,来在 invoke() 方法中对被代理对象的目标方法进行增强和调用,这些通过下面这段代码就看懂:

// 我的代理工厂类,实现了InvocationHandler 接口
public class MyProxyFactory implements InvocationHandler {private Object target = null;public Object getInstance(Object target) {this.target = target;return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object res = null;System.out.println("前置增强");res = method.invoke(target, args);System.out.println("后置增强");return res;}
}

但代理对象是如何生成的?invoke()方法 又是如何被调用的呢?

带着这两个疑问接着看下面的代码:

// 定义一个 test 的接口
public interface MyInterface {void play();
}/*** 基于JDK代理的标准,该类实现了接口 MyInterface 和接口的 play() 方法,可以作为被代理类*/
public class TargetObject implements MyInterface{@Overridepublic void play() {System.out.println("TargetObject play");}
}

基于上面的可以杯代理的TargetObject 类, 来做下测试,代码如下:

public class ProxyTest {public static void main(String[] args) {TargetObject target = new TargetObject();/*** MyProxyFactory 实现了 InvocationHandler接口,其中的 getInstance()方法就是利用Proxy类生成并返回了target目标对象的代理对象;* MyProxyFactory 持有对 target 的引用,可以在invoke()中对目标方法前置后置做增强处理,并完成对target相应方法的调用。*/MyProxyFactory proxyFactory = new MyProxyFactory();/*** 这个mi就是JDK生成的代理类,即动态生成的代理类$Proxy0的实例,该实例中的方法都持有对invoke()方法的回调,* 所以当调用其方法时,就能够执行invoke()中的增强处理*/MyInterface mi = (MyInterface) proxyFactory.getInstance(target);// 可以看到 mi 的 Class 到底是什么System.out.println(mi.getClass());/*** 这里实际上调用的就是$Proxy0代理类实例对象中对play()方法的实现,* 结合下面的代码可以看到play()方法 通过 super.h.invoke() 完成了对InvocationHandler对象(proxyFactory)中invoke()方法 的回调,* 所以我们才能够通过 invoke()方法实现对 target对象方法的前置后置增强处理*/mi.play();// 总的来说,JDK动态生成的代理类中对 invoke()方法进行了回调,就是在 invoke()方法中完成target目标方法的调用,及前置后置增强,}
}// 运行结果:
class com.sun.proxy.$Proxy0
前置增强
TargetObject play
后置增强

由上面的分析我们有的大致了解到实际生产的代理对象类是class com.sun.proxy.$Proxy0;因为代理类是运行时生成的,运行结束也就看不到了,为了我们方便的看生成的代理类究竟是长啥样, 我们可以借助 JDK 提供的工具类(ProxyGenerator)的 generateProxyClass 方法生成代理类的字节码,并保存为 .class文件。具体实现如下代码:

public class ProxyTest {@Testpublic void generatorSrc() {// 调用 generateProxyClass 方法生成字节码byte[] bytesFile = ProxyGenerator.generateProxyClass("$Proxy0", TargetObject.class.getInterfaces());// 将字节码写入文件String path = System.getProperty("user.dir") + "\\$Proxy0.class";File file = new File(path);try (FileOutputStream fos = new FileOutputStream(file)) {fos.write(bytesFile);fos.flush();} catch (IOException e) {throw new RuntimeException(e);}}
}

接下来我们可以借助Java反编译工具, 或者直接用idea打开$Proxy0.class文件一探究竟。

四、代理类结构解析

打开的$Proxy0.class结构如下:

// 生成的代理类示例(反编译后)
// Proxy 生成的代理类,可以看到,其继承了 Proxy,并且实现了 被代理类的接口MyInterface
public final class $Proxy0 extends Proxy implements MyInterface {// 静态方法引用表private static Method m1;private static Method m2;private static Method m3;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 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 play() throws  {try {// 关键调用:转发至InvocationHandler// 这个 h 其实就是我们调用 Proxy.newProxyInstance()方法 时传进去的 MyProxyFactory对象(它实现了InvocationHandler接口),// 该对象的 invoke()方法 中实现了对目标对象的目标方法的增强。// 看到这里,利用动态代理实现方法增强的实现原理就很清晰了super.h.invoke(this, m3, (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"));m2 = Class.forName("java.lang.Object").getMethod("toString");// 实例化 MyInterface 的 play()方法m3 = Class.forName("com.umzhang.springwebdemo.testproxy.MyInterface").getMethod("play");m0 = Class.forName("java.lang.Object").getMethod("hashCode");} catch (NoSuchMethodException var2) {throw new NoSuchMethodError(var2.getMessage());} catch (ClassNotFoundException var3) {throw new NoClassDefFoundError(var3.getMessage());}}
}

核心设计:

  • 继承Proxy父类,持有InvocationHandler实例
  • 静态块初始化接口方法引用
  • 每个代理方法直接调用InvocationHandler.invoke()

四、方法调用全流程

在这里插入图片描述
关键环节:

  1. 代理方法拦截:代理类方法被调用
  2. 统一转发:调用InvocationHandler.invoke()
  3. 反射执行:通过method.invoke(target, args)调用目标方法
  4. 增强扩展点:在invoke()中可插入前后逻辑

六、关键特性与限制

✅ 核心优势:

  • 动态字节码生成,使用ProxyGenerator动态生成.class文件
  • 类名格式:$ProxyN(N为自增数字)

⚠️ 使用限制

  • 接口依赖:目标类必须实现至少一个接口(无法代理无接口的类)
  • final方法:不能代理final方法(代理类通过继承实现,无法重写final方法)
  • 私有方法:只能代理接口声明的方法(私有方法不会被拦截)

与CGLIB代理对比
在这里插入图片描述

总结

JDK动态代理通过运行时字节码生成 + 方法调用转发两大核心机制,实现了优雅的代理模式:

  1. 技术价值:解耦业务逻辑与横切关注点(如日志、事务);为Spring等框架提供AOP底层支持。
  2. 应用边界:适用于基于接口的代理场景;性能敏感场景需关注反射调用开销(可结合JIT优化)。

JDK 动态代理通过 运行时生成代理类字节码 + 统一方法转发到 InvocationHandler 实现动态代理。其设计优雅地结合了 Java 反射机制与类加载机制,成为 Java 生态中 AOP 和中间件开发的基础技术。尽管存在接口依赖的限制,但在 Spring 等框架的巧妙封装下,仍被广泛应用于企业级开发。
掌握其原理,能更深入理解Java生态中 AOP 编程、RPC 框架、Spring 容器、Mock 测试 等技术的实现本质。


End!

http://www.dtcms.com/wzjs/206941.html

相关文章:

  • 网络网站建设属于什么费用自己的网站怎么推广
  • 超大型网站建设推广网站文案
  • 做刷单网站犯法吗网络培训心得
  • 万维网使用的网站淘宝怎么优化关键词排名
  • 呼和浩特网站建设百度网页广告怎么做
  • 男女做 自拍视频网站火蝠电商代运营公司
  • 主题 外贸网站 模板下载免费网站搭建
  • 人才招聘网站怎么做seo是什么的缩写
  • 南昌专业网站优化推广百度应用app
  • 网站建设亮点深圳龙岗区布吉街道
  • 平湖企业网站建设新业务在线软件下载
  • 全面的河南网站建设seo教学网站
  • 个人备案网站sem搜索
  • 专业做英文网站竞价服务托管价格
  • 网站开发合同模板免费网站推广seo
  • 陕西高端建设网站全网最好的推广平台
  • 怎么做frontpage网站优搜云seo
  • 好的品牌设计网站有哪些百度手机浏览器
  • 网站开发职业认知小结国际热点新闻
  • uc网站模板成都百度业务员电话
  • 针对人群不同 网站做细分seo关键词排名教程
  • 做 淘宝客最大的网站是叫什么做seo网页价格
  • 乐清外贸网站建设推广方案的推广内容怎么写
  • 交互式网站建设百度关键字
  • 企业做网站的优势网站推广在线推广
  • wordpress网站维护页面模板视频号关键词搜索排名
  • 建设工程八大员考试网站搜索引擎营销简称seo
  • 网站建设需要注意哪些事项成都seo优化
  • 中国政府网站建设与应用国际十大市场营销公司
  • 企业品牌网站建设多少钱百度识图在线使用