Cglib和jdk动态代理

  • 前言:动态代理解决了方法之间的紧耦合,IOC解决了类与类之间的紧耦合。

Cglib和jdk动态代理的区别?
1、Jdk动态代理:利用拦截器(必须实现InvocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理
2、 Cglib动态代理:利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成子类来处理
什么时候用cglib什么时候用jdk动态代理?
1、目标对象生成了接口 默认用JDK动态代理
2、如果目标对象使用了接口,可以强制使用cglib
3、如果目标对象没有实现接口,必须采用cglib库,Spring会自动在JDK动态代理和cglib之间转换
JDK动态代理和cglib字节码生成的区别?
1、JDK动态代理只能对实现了接口的类生成代理,而不能针对类
2、Cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,并覆盖其中方法的增强,但是因为采用的是继承,所以该类或方法最好不要生成final,对于final类或方法,是无法继承的
Cglib比JDK快?
1、cglib底层是ASM字节码生成框架,但是字节码技术生成代理类,在JDL1.6之前比使用java反射的效率要高
2、在jdk6之后逐步对JDK动态代理进行了优化,在调用次数比较少时效率高于cglib代理效率
3、只有在大量调用的时候cglib的效率高,但是在1.8的时候JDK的效率已高于cglib
4、Cglib不能对声明final的方法进行代理,因为cglib是动态生成代理对象,final关键字修饰的类不可变只能被引用不能被修改
Spring如何选择是用JDK还是cglib?
1、当bean实现接口时,会用JDK代理模式
2、当bean没有实现接口,用cglib实现
3、可以强制使用cglib(在spring配置中加入<aop:aspectj-autoproxy proxyt-target-class=”true”/>)
一. Cglib原理
动态生成一个要代理的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截技术拦截所有的父类方法的调用,顺势织入横切逻辑,它比Java反射的jdk动态代理要快
Cglib是一个强大的、高性能的代码生成包,它被广泛应用在许多AOP框架中,为他们提供方法的拦截

最底层的是字节码Bytecode,字节码是java为了保证依次运行,可以跨平台使用的一种虚拟指令格式
在字节码文件之上的是ASM,只是一种直接操作字节码的框架,应用ASM需要对Java字节码、class结构比较熟悉
位于ASM上面的是Cglib,groovy、beanshell,后来那个种并不是Java体系中的内容是脚本语言,他们通过ASM框架生成字节码变相执行Java代码,在JVM中程序执行不一定非要写java代码,只要能生成java字节码,jvm并不关系字节码的来源
位于cglib、groovy、beanshell之上的就是hibernate和spring AOP
最上面的是applications,既具体应用,一般是一个web项目或者本地跑一个程序、
使用cglib代码对类做代理?
使用cglib定义不同的拦截策略?
构造函数不拦截方法
用MethodInterceptor和Enhancer实现一个动态代理
Jdk中的动态代理
JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接口实现的,但是JDK中所有要进行动态代理的类必须要实现一个接口,也就是说只能对该类所实现接口中定义的方法进行代理,这在实际编程中有一定的局限性,而且使用反射的效率也不高
Cglib实现
使用cglib是实现动态代理,不受代理类必须实现接口的限制,因为cglib底层是用ASM框架,使用字节码技术生成代理类,你使用Java反射的效率要高,cglib不能对声明final的方法进行代理,因为cglib原理是动态生成被代理类的子类

三种代理的对比
在上面,我们使用CGLIB动态代理实现了火车站卖票的案例,相信大家对于CGLIB动态代理也有了一定的认识。当然,对于CGLIB动态代理的底层实现原理,在本讲我就不再为大家进行详细讲述了。有兴趣的同学可以自己使用阿里巴巴提供的Java诊断工具进行一个代理类的获取,然后自己去分析一下。

在本小节,我们来对比一下以上三种代理,即静态代理、JDK动态代理和CGLIB动态代理。

JDK动态代理和CGLIB动态代理
使用CGLIB实现动态代理,CGLIB底层采用ASM字节码生成框架,使用字节码技术生成代理类,在JDK1.6之前比使用Java反射的效率要高。唯一需要注意的是,CGLIB不能对声明为final的类或者方法进行代理,因为CGLIB原理是动态生成被代理类的子类(或者目标类的子类)。

在JDK1.6、JDK1.7、JDK1.8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLIB代理效率,只有当进行大量调用的时候,JDK1.6和JDK1.7比CGLIB代理效率低一点,但是到JDK1.8的时候,JDK代理效率高于CGLIB代理。而现在几乎所有的公司基本上都是使用的JDK1.8及以上的版本,所以又可以这样说,JDK代理的效率要高于CGLIB的。

那么以后我们在真正使用的时候,到底应该使用的是JDK代理还是CGLIB代理呢?若有接口则使用JDK动态代理,若没有接口则使用CGLIB代理。

动态代理和静态代理
动态代理与静态代理相比较,最大的好处是接口(也可以是类)中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)了。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转(或者重写)了。

以上这段话说的什么意思啊?这里我给大家解释一下。

如果是JDK动态代理的话,那么它集中都会调用invoke方法,因为JDK动态代理是对接口里面的方法进行代理的,而要是接口里面定义了多个方法,那么通过代理对象调用任何一个方法,最终执行的都是invoke方法,所以这是不是集中进行了一个处理啊!

对于CGLIB动态代理也是同样的一个道理,MethodInterceptor规范接口里面的intercept方法对我们目标对象中的方法进行一个增强,也即对目标类进行了一个代理,而要是目标类里面有多个方法的话,那么通过代理对象调用任何一个方法,最终执行的都将会是这个intercept方法,这是不是也集中进行了一个处理啊!

最后,如果接口增加了一个方法,静态代理模式除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法,这就增加了代码维护的复杂度。而动态代理则不会出现该问题,因为你在接口或者类里面去新添加了一个方法的话,我们的代理类不需要进行改变的,因为它是动态的在内存中生成的。

代理模式的优缺点以及使用场景
接下来,我们来看下代理模式的优缺点以及使用场景。

优缺点
优点
代理模式的优点,我总结了下面三个。

代理模式在客户端与目标对象之间起到了一个中介作用和保护目标对象的作用。有了代理模式之后,访问者只需要去访问代理对象而无须直接去访问目标对象了,这就对目标对象起到了一个保护的作用
代理对象可以扩展目标对象的功能。也就是说,代理对象可以对目标对象里面的功能进行增强,例如,在上面火车站卖票的案例中,代售点就是代理对象,它可以对火车站卖票的功能进行增强,增强的逻辑就是收取一些服务费用。当然了,你可以在你自己的业务里面进行相应的一个增强
代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,注意,主要降低的是访问者和目标对象之间的一个耦合度
缺点
增加了系统的复杂度。对于代理对象,尤其是动态代理,你会发现实现起来还是稍微有点麻烦的,如果你在不了解它底层原理的情况下去实现,那么会特别特别麻烦,而且特别不好理解。

使用场景
使用场景的话,我也总结了下面三个。

远程(Remote)代理

本地服务通过网络请求远程服务(也就是说远程的去调用里面的方法或者功能)。为了实现本地到远程的通信,我们需要实现网络通信,处理其中可能的异常。为了良好的代码设计和可维护性,我们应将网络通信部分隐藏起来,只暴露给本地服务一个接口,通过该接口即可访问远程服务提供的功能,而不必过多关心通信部分的细节。

其实,这个就是RPC思想,也即远程去调用方法。后期我们可能会用到很多RPC的框架,它底层就是这么一个思想,也就是远程代理,只不过在这儿我就不做详细的讲解了。

防火墙(Firewall)代理

当你将浏览器配置成使用代理功能时,防火墙就将你的浏览器的请求转给互联网;当互联网返回响应时,代理服务器再把它转给你的浏览器。

其实,这个就是所谓的VPN,通过它我们就能访问外边的一些网络了。

保护(Protect or Access)代理

控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。

使用了代理模式之后,访问者直接访问的是代理对象而不再是目标对象,这样,在代理对象里面,我们就可以给不同的用户提供不同级别的使用权限了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值