spring 如何决定使用jdk动态代理和cglib(网易面试题)

转载 2016年08月31日 11:05:06
Spring1.2:
将事务代理工厂[TransactionProxyFactoryBean] 或 自动代理拦截器[BeanNameAutoProxyCreator]
的 proxyTargetClass 属性,设置为true,则使用CGLIB代理,此属性默认为false,使用JDK动态代理.
以下引用 Spring Framework reference 2.0.5:
Spring2.0:

Spring AOP部分使用JDK动态代理或者CGLIB来为目标对象创建代理。(建议尽量使用JDK的动态代理)

如果被代理的目标对象实现了至少一个接口,则会使用JDK动态代理。所有该目标类型实现的接口都将被代理。若该目标对象没有实现任何接口,则创建一个CGLIB代理。

如果你希望强制使用CGLIB代理,(例如:希望代理目标对象的所有方法,而不只是实现自接口的方法)那也可以。但是需要考虑以下问题:

无法通知(advise)Final 方法,因为他们不能被覆写。 
你需要将CGLIB 2二进制发行包放在classpath下面,与之相较JDK本身就提供了动态代理 
强制使用CGLIB代理需要将 |aop:config| 的 proxy-target-class 属性设为true:

|aop:config proxy-target-class="true"|
...
|/aop:config|

当需要使用CGLIB代理和@AspectJ自动代理支持,请按照如下的方式设置 |aop:aspectj-autoproxy| 的 proxy-target-class 属性:

|aop:aspectj-autoproxy proxy-target-class="true"/|

而实际使用的过程中才会发现细节问题的差别,The devil is in the detail.JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理。
CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比JDK强。
Spring是依靠什么来判断采用哪种代理策略来生成AOP代理呢?以下代码就是Spring的判断逻辑  

    //org.springframework.aop.framework.DefaultAopProxyFactory   
    
//参数AdvisedSupport 是Spring AOP配置相关类   
    public AopProxy createAopProxy(AdvisedSupport advisedSupport)   
            
throws AopConfigException {   
        
//在此判断使用JDK动态代理还是CGLIB代理   
        if (advisedSupport.isOptimize() || advisedSupport.isProxyTargetClass()   
                
|| hasNoUserSuppliedProxyInterfaces(advisedSupport)) {   
            
if (!cglibAvailable) {   
                
throw new AopConfigException(   
                        
"Cannot proxy target class because CGLIB2 is not available. "  
                                
+ "Add CGLIB to the class path or specify proxy interfaces.");   
              }   
            
return CglibProxyFactory.createCglibProxy(advisedSupport);   
          } 
else {   
            
return new JdkDynamicAopProxy(advisedSupport);   
          }   
      }  

advisedSupport.isOptimize()与advisedSupport.isProxyTargetClass()默认返回都是false,所以在默认情况下目标对象有没有实现接口决定着Spring采取的策略,当然可以设置advisedSupport.isOptimize()或者advisedSupport.isProxyTargetClass()返回为true,这样无论目标对象有没有实现接口Spring都会选择使用CGLIB代理。

所以在默认情况下,如果一个目标对象如果实现了接口Spring则会选择JDK动态代理策略动态的创建一个接口实现类(动态代理类)来代理目标对象,可以通俗的理解这个动态代理类是目标对象的另外一个版本,所以这两者之间在强制转换的时候会抛出java.lang.ClassCastException。而所以在默认情况下,如果目标对象没有实现任何接口,Spring会选择CGLIB代理, 其生成的动态代理对象是目标类的子类。

上说的是默认情况下,也可以手动配置一些选项使Spring采用CGLIB代理。 
org.springframework.transaction.interceptor.TransactionProxyFactoryBean是org.springframework.aop.framework. ProxyConfig的子类,所以可以参照ProxyConfig里的一些设置如下所示,将optimize和proxyTargetClass任意一个设置为true都可以强制Spring采用CGLIB代理。

如果当需要使用CGLIB代理和@AspectJ自动代理支持,请按照如下的方式设置 |aop:aspectj-autoproxy| 的 proxy-target-class 属性: 
|aop:aspectj-autoproxy proxy-target-class="true"/|

这样使用CGLIB代理也就不会出现前面提到的ClassCastException问题了,也可以在性能上有所提高,关键是对于代理对象是否继承接口可以统一使用。

Spring的两种代理JDK和CGLIB的区别浅谈

一、原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。 而cglib动态代理是利用asm开源包,对代理对象类的cla...
  • u013126379
  • u013126379
  • 2016年08月04日 17:39
  • 17159

Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)

第一种代理即Java的动态代理方式上一篇已经分析,在这里不再介绍,现在我们先来了解下GCLIB代理是什么?它又是怎样实现的?和Java动态代理有什么区别?cglib(Code Generation L...
  • Intlgj
  • Intlgj
  • 2010年06月16日 14:09
  • 26347

Spring的两种代理方式:JDK动态代理和CGLIB动态代理

代理模式代理模式的英文叫做Proxy或Surrogate,中文都可译为”代理“,所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象...
  • cckevincyh
  • cckevincyh
  • 2017年02月10日 14:04
  • 7764

Spring的两种代理JDK和CGLIB的区别浅谈

原文地址:http://blog.csdn.net/u013126379/article/details/52121096 一、原理区别: Java动态代理是利用反射机制生成一个实现代理接口的匿名类...
  • tanga842428
  • tanga842428
  • 2016年10月01日 11:04
  • 3649

Spring AOP中强制使用CGLIB代理

spring官方文档中关于aop的描述如下:Spring AOP defaults to using standard JDK dynamic proxies for AOP proxies. Thi...
  • dushenzhi
  • dushenzhi
  • 2016年10月09日 20:08
  • 4535

Spring中AOP实现的两种方式之JDK和cglib的动态代理

AOP的实现原理: 都是基于代理模式,都是生成一个大代理对象 静态AOP: AspectJ实现的AOP, 将切面代码直接编译到Java类文件中 ...
  • he90227
  • he90227
  • 2016年08月31日 20:03
  • 2675

spring学习(二)—通知

通知类型1、Spring只支持方法通知,也就是说,只能在方法的前后进行通知,而不能在属性前后进行通知。 2、Spring支持四种通知类型:目标方法调用前(before),目标方法调用后(after)...
  • mingxin95
  • mingxin95
  • 2016年07月03日 11:36
  • 907

Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)

第一种代理即Java的动态代理方式上一篇已经分析,在这里不再介绍,现在我们先来了解下GCLIB代理是什么?它又是怎样实现的?和Java动态代理有什么区别? cglib(Code Generation...
  • caomiao2006
  • caomiao2006
  • 2016年05月02日 09:24
  • 6109

Java动态代理模式jdk和cglib的2种实现以及二者的区别(AOP面向切面的前奏)

关于动态代理模式里面有两种实现,一种是jdk实现,一种是cglib来实现。 下面来整jdk来实现动态代理的Java实例。 jdk动态代理模式里面有个拦截器的概念,在jdk中,只要实现了Invocati...
  • qq_27093465
  • qq_27093465
  • 2016年11月25日 21:40
  • 2584

【SpringAOP】——JDK动态代理

Spring的动态代理有两种:一是JDK的动态代理(需要提供接口);另一个是cglib动态代理(通过修改字节码来实现代理)。大部分情况下,一般使用JDK动态代理,因为JDK动态代理的速度要比CGLIB...
  • u010164936
  • u010164936
  • 2016年09月06日 15:40
  • 706
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:spring 如何决定使用jdk动态代理和cglib(网易面试题)
举报原因:
原因补充:

(最多只允许输入30个字)