Java动态代理四种实现方式详解

编程之家收集整理的这篇文章主要介绍了Java动态代理四种实现方式详解编程之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

这篇文章主要介绍了Java四种动态代理实现方式,对于开始学习java动态代理或者要复习java动态代理的朋友来讲很有参考价值,有感兴趣的朋友可以参考一下

代理模式也是一种非常常见的设计模式。了解Spring框架的都知道,Spring AOP 使用的就是动态代理模式。今天就来系统的重温一遍代理模式。

在现实生活中代理是随处可见的,当事人因某些隐私不方便出面,或者当事人不具备某些相关的专业技能,而需要一个职业人员来完成一些专业的操作, 也可能由于当事人没有时间处理事务,而聘用代理人出面。而在软件设计中,使用代理模式的地方也很多,由于安全原因,屏蔽客户端直接访问真实对象, 或者为了提升系统性能,使用代理模式实现延迟加载,还有就是AOP,对委托类的功能进行增强等。

一、代理模式的结构

代理模式的主要参与者有4个,如下图所示:

角色

作用

Subject

主题接口,定义了代理类和委托类的公共对外方法,也是代理类代理委托类的方法

RealSubject

委托类,真实主题,真正实现业务逻辑的类

Proxy

代理类,代理和封装委托类

Client

客户端,使用代理类和主题接口完成业务逻辑

loading="lazy" alt="" />角色作用Subject主题接口,定义了代理类和委托类的公共对外方法,也是代理类代理委托类的方法RealSubject委托类,真实主题,真正实现业务逻辑的类Proxy代理类,代理和封装委托类Client客户端,使用代理类和主题接口完成业务逻辑

二、代理模式的实现

代理模式一般分为静态代理和动态代理两种:

静态代理,顾名思义,就是提前创建好代理类文件并在程序运行前已经编译成字节码。

动态代理,是指在运行时动态生成代理类,即代理类的字节码将在运行时生成并载入到ClassLoader中。

了解了两种代理模式大概区别后,接下来就以一个短信发送功能增强的示例来详细阐述两种代理的实现方式。

1、静态代理实现

第一步,定义主题接口,该接口只有一个send方法

public interface ISender { public boolean send(); }

第二步,定义主题真正实现类:

public class SmsSender implements ISender { public boolean send() { System.out.println("sending msg"); return true; } }

第三步,创建代理类,封装实现类:

public class ProxySender implements ISender { private ISender sender; public ProxySender(ISender sender){ this.sender = sender; } public boolean send() { System.out.println("处理前"); boolean result = sender.send(); System.out.println("处理后"); return result; } }

第四步,客户端调用

@Test public void testStaticProxy(){ ISender sender = new ProxySender(new SmsSender()); boolean result = sender.send(); System.out.println("输出结果:" + result); }

以上就实现了一个简单的静态代理,很明显,静态代理需要为每个真实主题定义一个形式上完全一样的封装类,

如果真实主题方法有所修改,那代理类也需要跟着修改,不利于系统的维护。

2、动态代理实现

与静态代理相比,动态代理有更多优势,动态代理不仅不需要定义代理类,甚至可以在运行时指定代理类的执行逻辑,从而大大提升系统的灵活性。

目前动态代理类的生成方法有很多,有JDK自带的动态代理、cglib、Javassist和ASM库等。

JDK动态代理:内置在JDK中,不需要引入第三方jar,使用简单,但功能比较弱。

cglib/Javassist:这两个都是高级的字节码生成库,总体性能比JDK动态代理好,且功能强大。

ASM:低级字节码生成工具,近乎使用bytecode编码,对开发人员要求最高。当然性能也是最好(相比前几种也不是很大的提升,这里不做具体介绍)。

以下实例依然以SmsSender和ISender作为被代理对象和接口进行试验。

1) JDK动态代理

JDK的动态代理需要实现一个处理方法调用的Handler,用于实现代理方法的内部逻辑,实现InvocationHandler接口。

public class JdkProxyHandler implements InvocationHandler { private Object target; public JdkProxyHandler(Object target){ this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("处理前"); Object result = method.invoke(target,args); System.out.println("处理后"); return result; } }

客户端调用

@Test public void testJdkProxy(){ ISender sender = (ISender) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{ISender.class}, new JdkProxyHandler(new SmsSender())); boolean result = sender.send(); System.out.println("代理对象:" + sender.getClass().getName()); System.out.println("输出结果:" + result); }

输出结果:

处理前

sending msg

处理后

代理对象:com.sun.proxy.$Proxy4

输出结果:true

这样实现一个简单的AOP就完成了,我们看到代理类的类型是com.sun.proxy.$Proxy4。那JDK是如何创建代理类?

首先从Proxy.newProxyInstance入手,来研究JDK是如何生成代理类:

public static Object newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h)

方法有3个参数:

loader:用哪个类加载器去加载代理对象,生成目标对象的代理需要确保其类加载器相同,所以需要将目标对象的类加载器作为参数传递。

interfaces:代理类需实现的接口列表,JDK动态代理技术需要代理类和目标对象都继承自同一接口,所以需要将目标对象的接口作为参数传递。

h:调用处理器,调用实现了InvocationHandler类的一个回调方法,对目标对象的增强逻辑在这个实现类中。

具体代码如下:

public static Object newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h) throws IllegalArgumentException { //1.检查 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. */ //获取代理类类型 Class> cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler. */ try { if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } //通过反射创建代理对象 final Constructor> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h;上一篇:详解领域驱动设计之事件驱动与CQRS下一篇:MyBatis Log 插件无法显示sql语句的原因解析 热门搜索

动态代理实现 

动态代理的两种方式 

动态代理模拟实现aop 

动态代理模式 

实现动态 

相关文章

Java动态代理四种实现方式详解

2021-09-10阅读(3379)评论(0)推荐()

这篇文章主要介绍了Java四种动态代理实现方式,对于开始学习java动态代理或者要复习java动态代理的朋友来讲很有参考价值,有感兴趣的朋友可以参考一下

详解java动态代理的2种实现方式

2021-11-15阅读(8961)评论(0)推荐()

目前Java开发包中包含了对动态代理的支持,但是其实现只支持对接口的的实现。这篇文章主要介绍了详解java动态代理的2种实现方式 ,有兴趣的可以了解一下。

Java 动态代理的多种实现方式

2021-10-11阅读(4052)评论(0)推荐()

动态代理实际上是JVM在运行期动态创建class字节码并加载的过程。本文讲述了Java 动态代理的多种实现方式,感兴趣的朋友可以选择适合自己的方式

Java动态代理的两种实现方式详解【附相关jar文件下载】

2021-10-10阅读(3948)评论(0)推荐()

这篇文章主要介绍了Java动态代理的两种实现方式,结合实例形式分析了java动态代理的相关原理、实现方法与操作技巧,并附带相关jar文件供读者下载,需要的朋友可...

Java代理模式实例详解【静态代理与动态代理】

2021-10-11阅读(3981)评论(0)推荐()

这篇文章主要介绍了Java代理模式,结合实例形式详细分析了java静态代理与动态代理模式相关概念、原理、操作技巧与注意事项,需要的朋友可以参考下

详解java动态代理模式

2021-10-05阅读(5840)评论(0)推荐()

这篇文章主要为大家详细介绍了java动态代理模式,总结一下代理模式,以及jdk,cglib代理模式用法,来理解代理模式,感兴趣的小伙伴们可以参考一下

Java动态代理实现_动力节点Java学院整理

2021-09-18阅读(5437)评论(0)推荐()

动态代理作为代理模式的一种扩展形式,广泛应用于框架(尤其是基于AOP的框架)的设计与开发,本文将通过实例来讲解Java动态代理的实现过程

取消

有人回复邮件通知

提交评论

© 2021 编程之家 

工信部备案号:琼ICP备2022000316号

总结

以上是编程之家为你收集整理的Java动态代理四种实现方式详解全部内容。

如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给好友。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

Java相关文章

Java是目前世界上最流行的计算机编程语言之一,也是很多人学IT时学习的主要语言,而且目前从PC端到移动平台都有着Java的身影,Java工程师的需求量依旧不低,在编程语言排行榜上依旧名列前茅。
为了提升处理效率,并发一直以来都是软件开发设计场景中无法绕过的话题。为了提升系统的整体并发吞吐量,程序员们可谓是煞费苦心。本文换个角度探讨下多线程并发相关的内容,全面了解下多线程并发世界的各种关联。
日期时间的处理,是软件开发中极其常见的场景,JAVA中与日期、时间相关的一些类与API方法也很多,这里结合平时的编码实践全面的整理了下,希望可以帮助大家厘清其中的门道,更加游刃有余的面对此方面的处理~
笔者结合在团队中多年的代码检视遇到的情况,结合平时项目编码实践经验,对Stream的核心要点与易混淆用法、典型使用场景等进行了详细的梳理总结,希望可以帮助大家对Stream有个更全面的认知,也可以更加
在分布式系统盛行的今天,缓存充当着扛压屏障的作用,一旦缓存出现问题,对系统影响也是致命的。本文我们一起聊聊如何安全且可靠的使用缓存,聊聊缓存击穿、缓存雪崩、缓存穿透以及数据一致性、热点数据淘汰机制等。
容器设计是项目编码中非常常见的一个场景,本文从项目中习以为常的一些场景作为切入点,聊一聊容器设计的一些思考、聊一聊元素遍历的思路、以及身为设计模式之一的迭代器模式。
在项目开发中,由于业务规划原因,经常会涉及到聚合信息处理类的场景,按照环节串行执行的时候往往最终响应耗时很长,JAVA对并行的处理场景支持已经很完善了,本文深度总结了应对策略,快来看看吧~
业界各大厂商或开源团队都会构建并提供一些缓存框架组件提供给开发者按需选择,这里就会涉及到一个标准规范的遵循问题,本文我们一起聊聊JCache API规范与SpringCache规范。