JDK和CGLIB动态代理区别

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。

前言
Github:https://github.com/yihonglei/thinking-in-spring

JDK动态代理实现原理(jdk8):https://blog.csdn.net/yhl_jxy/article/details/80586785

CGLIB动态代理实现原理:https://blog.csdn.net/yhl_jxy/article/details/80633194

一 JDK和CGLIB动态代理原理
1、JDK动态代理
利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生成一个实现代理接口的匿名类,

在调用具体方法前调用InvokeHandler来处理。

2、CGLIB动态代理
利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

3、何时使用JDK还是CGLIB?
1)如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP。

2)如果目标对象实现了接口,可以强制使用CGLIB实现AOP。

3)如果目标对象没有实现了接口,必须采用CGLIB库,Spring会自动在JDK动态代理和CGLIB之间转换。

4、如何强制使用CGLIB实现AOP?
1)添加CGLIB库(aspectjrt-xxx.jar、aspectjweaver-xxx.jar、cglib-nodep-xxx.jar)

2)在Spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

5、JDK动态代理和CGLIB字节码生成的区别?
1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类。

2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,

     并覆盖其中方法实现增强,但是因为采用的是继承,所以该类或方法最好不要声明成final,

     对于final类或方法,是无法继承的。

6、CGlib比JDK快?
1)使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,

在jdk6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,

因为CGLib原理是动态生成被代理类的子类。

2)在jdk6、jdk7、jdk8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLIB代理效率,

只有当进行大量调用的时候,jdk6和jdk7比CGLIB代理效率低一点,但是到jdk8的时候,jdk代理效率高于CGLIB代理,

总之,每一次jdk版本升级,jdk代理效率都得到提升,而CGLIB代理消息确有点跟不上步伐。

7、Spring如何选择用JDK还是CGLIB?
1)当Bean实现接口时,Spring就会用JDK的动态代理。

2)当Bean没有实现接口时,Spring使用CGlib是实现。

3)可以强制使用CGlib(在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)。

二 代码实例
接口:

package com.jpeony.spring.proxy.compare;/*** 用户管理接口(真实主题和代理主题的共同接口,这样在任何可以使用真实主题的地方都可以使用代理主题代理。)* --被代理接口定义*/
public interface IUserManager {void addUser(String id, String password);
}


实现类:

package com.jpeony.spring.proxy.compare;/*** 用户管理接口实现(被代理的实现类)*/
public class UserManagerImpl implements IUserManager {@Overridepublic void addUser(String id, String password) {System.out.println("======调用了UserManagerImpl.addUser()方法======");}
}


JDK代理实现:

package com.jpeony.spring.proxy.compare;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** JDK动态代理类*/
public class JDKProxy implements InvocationHandler {/** 需要代理的目标对象 */private Object targetObject;/*** 将目标对象传入进行代理*/public Object newProxy(Object targetObject) {this.targetObject = targetObject;//返回代理对象return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(), this);}/*** invoke方法*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 一般我们进行逻辑处理的函数比如这个地方是模拟检查权限checkPopedom();// 设置方法的返回值Object ret = null;// 调用invoke方法,ret存储该方法的返回值ret  = method.invoke(targetObject, args);return ret;}/*** 模拟检查权限的例子*/private void checkPopedom() {System.out.println("======检查权限checkPopedom()======");}
}


CGLIB代理实现:

package com.jpeony.spring.proxy.compare;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** CGLibProxy动态代理类*/
public class CGLibProxy implements MethodInterceptor {/** CGLib需要代理的目标对象 */private Object targetObject;public Object createProxyObject(Object obj) {this.targetObject = obj;Enhancer enhancer = new Enhancer();enhancer.setSuperclass(obj.getClass());enhancer.setCallback(this);Object proxyObj = enhancer.create();// 返回代理对象return proxyObj;}@Overridepublic Object intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {Object obj = null;// 过滤方法if ("addUser".equals(method.getName())) {// 检查权限checkPopedom();}obj = method.invoke(targetObject, args);return obj;}private void checkPopedom() {System.out.println("======检查权限checkPopedom()======");}
}

客户端测试类:

package com.jpeony.spring.proxy.compare;/*** 代理模式[[ 客户端--》代理对象--》目标对象 ]]*/
public class Client {public static void main(String[] args) {System.out.println("**********************CGLibProxy**********************");CGLibProxy cgLibProxy = new CGLibProxy();IUserManager userManager = (IUserManager) cgLibProxy.createProxyObject(new UserManagerImpl());userManager.addUser("jpeony", "123456");System.out.println("**********************JDKProxy**********************");JDKProxy jdkPrpxy = new JDKProxy();IUserManager userManagerJDK = (IUserManager) jdkPrpxy.newProxy(new UserManagerImpl());userManagerJDK.addUser("jpeony", "123456");}
}


程序运行结果:

三 JDK和CGLIB动态代理总结
JDK代理是不需要第三方库支持,只需要JDK环境就可以进行代理,使用条件:

1)实现InvocationHandler 

2)使用Proxy.newProxyInstance产生代理对象

3)被代理的对象必须要实现接口

CGLib必须依赖于CGLib的类库,但是它需要类来实现任何接口代理的是指定的类生成一个子类,

覆盖其中的方法,是一种继承但是针对接口编程的环境下推荐使用JDK的代理;
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/447487.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对比Ruby和Python的垃圾回收(2):代式垃圾回收机制

本文由 伯乐在线 - 熊崽Kevin 翻译自 patshaughnessy。欢迎加入 技术翻译小组。转载请参见文章末尾处的要求。对比Ruby和Python的垃圾回收&#xff08;1&#xff09; 上周&#xff0c;我根据之前在RuPy上做的一个名为“Visualizing Garbage Collection in Ruby and Python.”…

@Deprecated 注解 (@Documented 、@Retention、@Target)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 // 在看 Unsafe 类源码时看到一个注解&#xff1a;Deprecated&#xff0c;似曾相识... Deprecated 用在类或者方法上&#xff0c;表示…

C++的未来和指针

本文由 伯乐在线 - 周昌鸿 翻译自 Meeting C。欢迎加入 技术翻译小组。转载请参见文章末尾处的要求。上周Meeting C2013结束后&#xff0c;我对C思考了很多&#xff0c;有一些内容和指针有关。在C 11中只对指针进行了小量的更新&#xff08;引入了nullptr&#xff09;&#xf…

Java魔法类:Unsafe应用解析

Unsafe是位于sun.misc包下的一个类&#xff0c;主要提供一些用于执行低级别、不安全操作的方法&#xff0c;如直接访问系统内存资源、自主管理内存资源等&#xff0c;这些方法在提升Java运行效率、增强Java语言底层资源操作能力方面起到了很大的作用。但由于Unsafe类使Java语言…

AMD迎接变革:加速OpenCL的未来

摘要&#xff1a;AMD在北京中关村皇冠假日酒店举办了以"迎接变革&#xff1a;加速进入OpenCL 的未来"为主题的技术培训。AMD Firepro显卡资深产品经理JC、OpenCL资深讲师陆教授、谢博士与大家探讨OpenCL技术将如何引领变革、铸造计算新纪元。 4月11日&#xff0c;AM…

JAVA中神奇的双刃剑--Unsafe

参考资料&#xff1a; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Java魔法类&#xff1a;sun.misc.Unsafe在openjdk8下看Unsafe源码 Unsafe介绍 在Oracle的Jdk8无法获取到sun.misc…

让AMD在中国发声 APU14技术创新大会首次在华召开

今日&#xff0c;AMD一年一度的开发者峰会“APU2014”在北京拉开帷幕&#xff0c;这也是AMD首次在美国之外的城市举办该活动。AMD全球副总裁、大中华区董事总经理潘晓明表示&#xff0c;大中华区是AMD重要的战略区域&#xff0c;AMD希望通过本次活动在中国制造巨大的声音&#…

Python已成美国顶尖高校中最受欢迎的入门编程语言

在最近的一份调查中显示&#xff0c;美国top高校中&#xff0c;Python已经成为教授计算机科学入门课程方面最受欢迎的语言。其中Top10 CS系中有8所使用Python&#xff0c;Top39 CS系中有24所&#xff0c;在入门课程中教授Python&#xff0c;可见其实用性的认可度很高。在我写下…

源码阅读 AtomicInteger

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 AtomicInteger 原子整数 可以原子更新的int值。 用于原子递增计数器等应用程序中&#xff0c;不能用作java.lang.Integer的替换。 扩展…

A饭福利,AMD Mantle API获众多游戏开发商青睐!

摘要&#xff1a;Videocardz整理了一份2014年—2015年支持AMD Mantle游戏列表&#xff0c;并公布了游戏开发商及游戏引擎的名称。已发布且支持Mantle的游戏主要有《战地4》、《神偷4》、《植物大战僵尸&#xff1a;花园战争》以及《狙击精英3》这四款。 现如今&#xff0c;越来…

linux 安装 maven 、解决:bash: mvn: command not found

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1、安装 wget 命令: yum -y install wget 2、下载maven安装包 wget http://mirrors.cnnic.cn/apache/maven/maven-3/3.5.4/binaries/a…

软件工程师必学的9件事

本文是html5tricks原创翻译&#xff0c;转载请看清文末的转载要求&#xff0c;谢谢合作&#xff01; 三年前&#xff0c;我还在巴塞罗那的神经科学实验室工作&#xff0c;忙着研究脑电波、教授心理学上的认知系统课程。而今天&#xff0c;我以设计和写软件为生。 你或许会满头…

Linux 的 chmod 命令,对一个目录及其子目录所有文件添加权限

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 对一个目录及其子目录所有文件添加权限 命令&#xff1a; chmod 777 -R ./html 给予html目录下可读可写可操作权限。 或者 chmod -R…

Linux 下压缩与解压.zip 和 .rar

1)对于.ziplinux下提供了zip和unzip程序&#xff0c;zip是压缩程序&#xff0c;unzip是解压程序。它们的参数选项很多&#xff0c;可用命令zip -help和unzip -help查看&#xff0c;这里只做简单介绍&#xff0c;举例说明一下其用法&#xff1a;# zip test.zip test.jpg test.pn…

优秀的程序员VS糟糕的程序员

优秀的程序员和一般的程序员差别在哪里&#xff1f;怎么才能成为优秀的程序员&#xff1f;我们选择了这个职业就要把他做好&#xff01; 优秀的程序员&#xff1a; 1、逻辑能力很强&#xff0c;这也是解决问题的关键。 2、分析能力。可以很好的解决复杂问题。 3、事情做得专…

图解 Java 常用数据结构

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 最近在整理数据结构方面的知识, 系统化看了下Java中常用数据结构, 突发奇想用动画来绘制数据流转过程. 主要基于jdk8, 可能会有些特性与…

程序员生存定律--使人生永动的势能

程序员生存定律这系列的目录在这里&#xff1a;程序员生存定律--目录 喜欢从头瞄的&#xff0c;可以移步。 ------------------------------------------------------------------------------- 这篇说的是精神&#xff0c;比较务虚&#xff0c;不感兴趣的可以略过。 在国内有…

int 和 Integer 的区别

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1、Integer是int的包装类&#xff0c;int则是java的一种基本数据类型 2、Integer变量必须实例化后才能使用&#xff0c;而int变量不需要…

度量术语之二:应用类和开发类生产率(实际度量案例)

一个令人震惊的事实是连生产率这种常见度量数据都没有一个简单的定义。连我们日常经常用到的公式&#xff1a;生产率工作产品/工作量&#xff08;工作产品可以是代码行&#xff0c;功能点&#xff0c;也可以是任何可以计数的东西&#xff0c;比如文档页数&#xff09;都是错误的…

注解 @ModelAttribute 运用详细介绍

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。1.ModelAttribute注释方法   例子&#xff08;1&#xff09;&#xff0c;&#xff08;2&#xff09;&#xff0c;&#xff08;3&#x…