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;表示…

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…

让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;可见其实用性的认可度很高。在我写下…

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;我以设计和写软件为生。 你或许会满头…

图解 Java 常用数据结构

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

编程语言 IDE 对比

IDE是集成开发环境的英文缩写&#xff0c;所谓集成开发环境&#xff0c;就是将你在开发过程中所需要的工具或功能集成到了一起&#xff0c;比如代码编写、分析、编译、调试等功能&#xff0c;从而最大化地提高开发者的工作效率。每种编程语言都有一些特定的IDE&#xff0c;本文…

程序员为什么那么难升职

一个有趣的现象是老程序员很难升职&#xff0c;如果你因为3K工资太低而要辞掉工作&#xff0c;你的上司宁可去外面找一个5K工资的新人&#xff0c;也不会来挽留你。那么程序员为什么那么难升职&#xff0c;这里总结了几点。你上司的问题你晋升困难&#xff0c;最大的主观原因在…

Docker 安装 Redis (Redis 配置)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 获取 redis 镜像 docker pull redis 不加版本号默认获取最新版本&#xff0c;也可以使用 docker search redis 查看镜像来源 查看本地镜像…

百度首席科学家 Andrew Ng谈深度学习的挑战和未来

摘要&#xff1a;7月7日上午&#xff0c;百度首席科学家Andrew Ng应邀做客中国科学院自动化研究所并做了《Deep Learning&#xff1a;Overview and trends》的学术报告。 【编者按】人工智能被认为是下一个互联网大事件&#xff0c;当下&#xff0c;谷歌、微软、百度等知名的高…

Linux 安装 jdk ( 两种方式 )

安装jdk有两种方法&#xff1a;手动安装 yum安装。 方式一&#xff1a; yum安装 1、查询要安装jdk的版本, 命令&#xff1a;yum -y list java* 2、安装jdk1.8 yum install -y java-1.8.0-openjdk.x86_64 3、查询jdk版本&#xff1a;java -version 这样就安装成功了。默认…

Linkedln技术高管Jay Kreps:Lambda架构剖析

摘要&#xff1a;Jay Kreps是Linkedln的一名在线数据架构技术高管&#xff0c;在日常工作中&#xff0c;Jay Kreps经常被问及有关Lambda架构的问题&#xff0c;为此他结合实际经验和个人体会&#xff0c;针对Lambda架构进行深度剖析&#xff0c;分析了它的优缺点以及采用的替代…

JWT ( JSON Web Token ) 入门教程

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 一、跨域认证的问题 互联网服务离不开用户认证。一般流程是下面这样。 1、用户向服务器发送用户名和密码。 2、服务器验证通过后&#x…

注解 @Target 用法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Target&#xff1a; Target说明了Annotation所修饰的对象范围&#xff1a;Annotation可被用于 packages、types&#xff08;类、接口、枚…

java 并发包之 LongAdder 源码分析

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 LongAdder是java8中新增的原子类&#xff0c;在多线程环境中&#xff0c;它比AtomicLong性能要高出不少&#xff0c;特别是写多的场景。…

解决:Command line is too long. In order to reduce its length classpath file can be used.

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 原本可以正常运行的项目&#xff0c;突然出现这个错&#xff1a; Command line is too long. In order to reduce its length class…