代理器(JDK Proxy 和 CGLib 有啥区别)

小鱼SEO专员2年前行业资讯1011

动态代理的常用实现方式是反射。反射机制是指程序在运行期间可以访问、检测和修改其本身状态或行为的一种能力,使用反射我们可以调用任意一个类对象,以及类对象中包含的属性及方法。

但动态代理不止有反射一种实现方式,例如,动态代理可以通过 CGLib 来实现,而 CGLib 是基于 ASM(一个 Java 字节码操作框架)而非反射实现的。简单来说,动态代理是一种行为方式,而反射或 ASM 只是它的一种实现手段而已。

JDK Proxy 和 CGLib 的区别主要体现在以下几个方面:

很多人经常会把反射和动态代理划为等号,但从严格意义上来说,这种想法是不正确的,真正能搞懂它们之间的关系,也体现了你扎实 Java 的基本功。和这个问题相关的知识点,还有以下几个:

很多人经常会把反射和动态代理划为等号,但从严格意义上来说,这种想法是不正确的,真正能搞懂它们之间的关系,也体现了你扎实 Java 的基本功。和这个问题相关的知识点,还有以下几个:

1.JDK Proxy 和 CGLib 的使用及代码分析

JDK Proxy 动态代理实现

JDK Proxy 动态代理的实现无需引用第三方类,只需要实现 InvocationHandler 接口,重写 invoke() 方法即可,整个实现代码如下所示:

以上程序的执行结果是:

动态代理之前的业务处理.

可以看出 JDK Proxy 实现动态代理的核心是实现 Invocation 接口,我们查看 Invocation 的源码,会发现里面其实只有一个 invoke() 方法,源码如下:

这是因为在动态代理中有一个重要的角色也就是代理器,它用于统一管理被代理的对象,显然 InvocationHandler 就是这个代理器,而 invoke() 方法则是触发代理的执行方法,我们通过实现 Invocation 接口来拥有动态代理的能力。

CGLib 的实现

在使用 CGLib 之前,我们要先在项目中引入 CGLib 框架,在 pom.xml 中添加如下配置:

CGLib 实现代码如下:

以上程序的执行结果是:

方法调用前业务处理.

可以看出 CGLib 和 JDK Proxy 的实现代码比较类似,都是通过实现代理器的接口,再调用某一个方法完成动态代理的,唯一不同的是,CGLib 在初始化被代理类时,是通过 Enhancer 对象把代理对象设置为被代理类的子类来实现动态代理的。因此被代理类不能被关键字 final 修饰,如果被 final 修饰,再使用 Enhancer 设置父类时会报错,动态代理的构建会失败。

2.Lombok 原理分析

在开始讲 Lombok 的原理之前,我们先来简单地介绍一下 Lombok,它属于 Java 的一个热门工具类,使用它可以有效地解决代码工程中那些繁琐又重复的代码,如 Setter、Getter、toString、equals 和 hashCode 等等,像这种方法都可以使用 Lombok 注解来完成。

例如,我们使用比较多的 Setter 和 Getter 方法,在没有使用 Lombok 之前,代码是这样的:

在使用 Lombok 之后,代码是这样的:

可以看出 Lombok 让代码简单和优雅了很多。

Tips:如果在项目中使用了 Lombok 的 Getter 和 Setter 注解,那么想要在编码阶段成功调用对象的 set 或 get 方法,我们需要在 IDE 中安装 Lombok 插件才行,比如 Idea 的插件如下图所示:

接下来讲讲 Lombok 的原理。

Lombok 的实现和反射没有任何关系,前面我们说了反射是程序在运行期的一种自省(introspect)能力,而 Lombok 的实现是在编译期就完成了,为什么这么说呢?

回到我们刚才 Setter/Getter 的方法,当我们打开 Person 的编译类就会发现,使用了 Lombok 的 @Data 注解后的源码竟然是这样的:

可以看出 Lombok 是在编译期就为我们生成了对应的字节码。

其实 Lombok 是基于 Java 1.6 实现的 JSR 269: Pluggable Annotation Processing API 来实现的,也就是通过编译期自定义注解处理器来实现的,它的执行步骤如下:

从流程图中可以看出,在编译期阶段,当 Java 源码被抽象成语法树(AST)之后,Lombok 会根据自己的注解处理器动态修改 AST,增加新的代码(节点),在这一切执行之后就生成了最终的字节码(.class)文件,这就是 Lombok 的执行原理。

3.动态代理知识点扩充

动态代理和静态代理的区别?静态代理其实就是事先写好代理类,可以手工编写也可以使用工具生成,但它的缺点是每个业务类都要对应一个代理类,特别不灵活也不方便,于是就有了动态代理。

动态代理的常见使用场景有 RPC 框架的封装、AOP(面向切面编程)的实现、JDBC 的连接等。

Spring 框架中同时使用了两种动态代理 JDK Proxy 和 CGLib,当 Bean 实现了接口时,Spring 就会使用 JDK Proxy,在没有实现接口时就会使用 CGLib,我们也可以在配置中指定强制使用 CGLib,只需要在 Spring 配置中添加 即可。

本文介绍了 JDK Proxy 和 CGLib 的区别,JDK Proxy 是 Java 语言内置的动态代理,必须要通过实现接口的方式来代理相关的类,而 CGLib 是第三方提供的基于 ASM 的高效动态代理类,它通过实现被代理类的子类来实现动态代理的功能,因此被代理的类不能使用 final 修饰。

除了 JDK Proxy 和 CGLib 之外,我们还讲了 Java 中常用的工具类 Lombok 的实现原理,它其实和反射是没有任何关系的;最后讲了动态代理的使用场景以及 Spring 中动态代理的实现方式,希望本文可以帮助到你。

相关文章

选房子如何看风水(怎样选风水好的房子)

如何看房屋风水 房屋风水解说 风水学知识在我们日常生活之中的体现是非常明显的,在我们日常生活当中体现最明显的地方就是房屋方面,现在人们在修房子、 方面都要看风水。这足以体现出了风水学知识对我们生活...

win10麦克风(来看看修复方法)

Win10系统中我们可以对声音设备进行自定义设置,在使用麦克风的时候,我们需要在系统中开启麦克风,才能够进行正常的声音录制。那遇到麦克风在Win10上不起作用,怎么办?下面我们就来看看修复方法。更多系...

荣成之窗,荣成信息港最新信息港

荣成信息港的最新招聘在哪里? 你好,这里提问没用。请到信息港社区提问,或者每天查看信息港招聘信息 这个答案是网友推荐的 荣成信息港如何注册登录? 打开主站,右上角有注册地点,然后根据提示输...

暗黑2雇佣兵光环(暗黑2野蛮人懒人玩法分享)

暗黑2雇佣兵光环(暗黑2野蛮人懒人玩法分享)

作者:乘风而去暗黑2这款游戏,千万个人,就有千万个玩法,每个人都有一个最适合自己的职业。经过几个月的游戏,我也摸到了最适合自己的打法——通用型的野蛮人,下面是跟大家一起来分享的内容:一、这套BUILD...

家用婴儿游泳池(家用婴儿游泳池实用吗)

很纠结是购买家用婴儿游泳池还是去游泳馆 建议还是去游泳馆吧,婴儿游泳馆的老师们都是专业的护理人员,她们相比家长来说更有经验,相比自己在家瞎忙活,还不如花点钱去婴儿游泳馆,楼主说的3年2w多也不是很贵...

10款儿童牙膏测评(舒客牙膏怎么样)

舒客宝贝儿童牙膏好用吗? 食品级材质,保护儿童脆弱的口腔环境;不含氟,避免氟元素过量引发氟斑牙;添加木糖醇成分,一样防蛀牙。 舒客牙膏怎么样?儿童能用么? 您好,建议不要用,儿童刷牙最好用属...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。