Java高级编程细节-动态代理-进阶高级开发必学技能

简介: 关于代理模式的话题有很多,在开发中经常用到的应该是静态代理模式,能很好的去耦合。动态代理是代理模式的另外一种实现。动态代理的区别在哪里?动态代理有什么好处?今天我们来分析下这些问题。

关于代理模式的话题有很多,

在开发中经常用到的应该是静态代理模式,能很好的去耦合。

动态代理是代理模式的另外一种实现。

动态代理的区别在哪里?

动态代理有什么好处?

今天我们来分析下这些问题。

回顾静态代理

之前我们分析过一次静态代理,

用代理模式优雅地写代码

一个典型的代理模式的 Proxy类像下面这样,

 

对于调用者来说,需要把构造好的实例传给代理,然后就可以用代理来替代操作真正的实例了。

静态代理的问题是,

在接口代码少的情况下一切没什么问题,但是当接口增加的时候,

Proxy 类就需要响应的增加接口,比方上面的 Func 接口,

 

刚开始可能只有一个 read()方法,后面慢慢发展到有了 write(),有了 mark(),

随着接口量的增加, Proxy的维护工作量也在逐步增加。

那么动态代理能怎么解决这种问题呢?

动态代理的实现

动态代理的实现步骤基本如下:

· 定义一个公共接口(像 Func)和实现类(像 User),这部分跟静态代理一样

· 定义一个 DynamicProxy类实现 InvocationHandler 接口,这个Proxy类似于静态代理的 Proxy然而不用实现 Func接口

· 调用 Proxy类来构造代理对象

在动态代理的实现中有两个东西非常重要,一个是 Proxy类,一个是 InvocationHandler接口,都位于 reflect包下,

我们来看第二个步骤所定义的 DynamicProxy是怎样的吧

 

它同样持有了委托对象实例,但是和静态代理不同,

它并没有实现委托对象的接口方法,

而只实现了 InvocationHandler的 invoke方法,然后调用了 method.invoke(this.user, objects);

可以留意下 invoke方法,后面我们继续分析,

这里再贴一下 Client类的代码,也就是使用 Proxy的地方,

 

跟静态代理不同的地方在于,虽然这里也需要实例化一个委托类的对象,并传给 Proxy的构造方法,

但这里所实例化的是 InvocationHandler对象,而不是 DynamicProxy的对象。

到这里就完成了一个动态代理的代码,输出结果如下

before invoke user method

user read

after invoke user method

比较&分析

· 先来说第二个步骤的 DynamicProxy的实现,

可以发现跟静态代理不同的地方在于,静态代理需要实现 Func接口的 read()方法,而动态代理实现的是 InvocationHandler的 invoke方法,

静态代理需要在不同的接口中去调用 User 接口的不同方法,

而动态代理在invoke被调用的过程中不需要关心需要调用 User 的哪个具体方法,

方法被封装在 method对象中,而所需要的参数则在 Object[] objects,

直接调用就可以

 

这里就意味着即使以后增加了 Func的接口,对于 DynamicProxy来说也不需要增加额外的维护量。

· Proxy.newProxyInstance干了什么

在静态代理里面,我们会直接用 new StaticProxy(user)构造出来的静态对象直接操作,

而在动态代理里面,我们操作的是 Proxy.newProxyInstance所构造出来的动态代理对象 proxyUser,

可能初次接触动态代理的同学在这里就概念混乱了,

"难道代理类不是 new DynamicProxy出来的对象吗?"

其实不是的,如果把 proxyUser的类名打印出来的话,

它会以 $ProxyN的形式存在,N从0开始,这个就是动态代理所生成的真正代理对象,

动态代理的意义就在于这里,$ProxyN 这个对象是在运行时创建的,

如果用代码来解释的话,$ProxyN的代码会像下面这样

 

这个才是真正的代理类。

欢迎工作一到五年的Java工程师朋友们加入Java架构开发:468947140

点击链接加入群聊【Java-BATJ企业级资深架构】:https://jq.qq.com/?_wv=1027&k=5zMN6JB

本群提供免费的学习指导 架构资料 以及免费的解答

不懂得问题都可以在本群提出来 之后还会有职业生涯规划以及面试指导

对本文感兴趣欢迎关注笔者,如有不同意见欢迎留言。

相关文章
|
12天前
|
安全 算法 Java
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第11天】 在Java中,高效的并发编程是提升应用性能和响应能力的关键。本文将探讨Java并发的核心概念,包括线程安全、锁机制、线程池以及并发集合等,同时提供实用的编程技巧和最佳实践,帮助开发者在保证线程安全的前提下,优化程序性能。我们将通过分析常见的并发问题,如竞态条件、死锁,以及如何利用现代Java并发工具来避免这些问题,从而构建更加健壮和高效的多线程应用程序。
|
4天前
|
IDE Java 物联网
《Java 简易速速上手小册》第1章:Java 编程基础(2024 最新版)
《Java 简易速速上手小册》第1章:Java 编程基础(2024 最新版)
11 0
|
4天前
|
IDE Java 数据库连接
使用 Java 进行桌面应用开发
【4月更文挑战第19天】Java 是一款广泛应用于企业级、网络和桌面应用开发的编程语言。其跨平台特性使Java程序能在不同操作系统上运行,而JDK提供了开发所需工具和库。使用Swing等GUI库构建用户界面,结合JDBC进行数据库操作,Socket实现网络通信。虽然面临性能和用户体验的挑战,但通过优化和选用合适的IDE,Java仍能开发出高效稳定的桌面应用。
|
4天前
|
监控 Java 开发者
掌握 Java 反射和动态代理
【4月更文挑战第19天】Java反射和动态代理提供强大功能和灵活性。反射允许运行时检查和操作类,获取类信息、动态调用方法,但可能带来性能损失和降低代码可读性。动态代理则用于创建代理对象,实现透明性和横切关注点分离,常用于日志、权限检查等。两者结合能实现更复杂功能。掌握这些技术能提升代码的灵活性和可扩展性,但也需注意性能和可读性。通过学习和实践,能更好地构建高效软件系统。
|
4天前
|
安全 Java 开发者
Java并发编程:深入理解Synchronized关键字
【4月更文挑战第19天】 在Java多线程编程中,为了确保数据的一致性和线程安全,我们经常需要使用到同步机制。其中,`synchronized`关键字是最为常见的一种方式,它能够保证在同一时刻只有一个线程可以访问某个对象的特定代码段。本文将深入探讨`synchronized`关键字的原理、用法以及性能影响,并通过具体示例来展示如何在Java程序中有效地应用这一技术。
|
5天前
|
前端开发 Java Go
开发语言详解(python、java、Go(Golong)。。。。)
开发语言详解(python、java、Go(Golong)。。。。)
|
5天前
|
人工智能 前端开发 Java
Java语言开发的AI智慧导诊系统源码springboot+redis 3D互联网智导诊系统源码
智慧导诊解决盲目就诊问题,减轻分诊工作压力。降低挂错号比例,优化就诊流程,有效提高线上线下医疗机构接诊效率。可通过人体画像选择症状部位,了解对应病症信息和推荐就医科室。
38 10
|
5天前
|
Java 关系型数据库 MySQL
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
UWB (ULTRA WIDE BAND, UWB) 技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。一套UWB精确定位系统,最高定位精度可达10cm,具有高精度,高动态,高容量,低功耗的应用。
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
|
5天前
|
安全 Java 调度
Java并发编程:深入理解线程与锁
【4月更文挑战第18天】本文探讨了Java中的线程和锁机制,包括线程的创建(通过Thread类、Runnable接口或Callable/Future)及其生命周期。Java提供多种锁机制,如`synchronized`关键字、ReentrantLock和ReadWriteLock,以确保并发访问共享资源的安全。此外,文章还介绍了高级并发工具,如Semaphore(控制并发线程数)、CountDownLatch(线程间等待)和CyclicBarrier(同步多个线程)。掌握这些知识对于编写高效、正确的并发程序至关重要。
|
6天前
|
缓存 分布式计算 监控
Java并发编程:深入理解线程池
【4月更文挑战第17天】在Java并发编程中,线程池是一种非常重要的技术,它可以有效地管理和控制线程的执行,提高系统的性能和稳定性。本文将深入探讨Java线程池的工作原理,使用方法以及在实际开发中的应用场景,帮助读者更好地理解和使用Java线程池。