IT忍者神龟之Java动态代理与CGLib代理

简介:
  1. <br>public class UserDAOImpl{  
  2. <br><br>    public void save() {  
  3. <br>        // TODO Auto-generated method stub  
  4. <br>        System.out.println("user saved");  
  5. <br>    }  
  6. <br>}  
  7. <br>//相关配置,省略了一些不相关内容  
  8. <br><bean id="userDAO" class="UserDAOImpl">  
  9. <br><bean id="userDAOProxy"  class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">   
  10. <br>    <property name="target">   
  11. <br>        <ref local="userDAO" />   
  12. <br>    </property>   
  13. <br></bean>  

   測试代码

  1.         ApplicationContext ctx =  
  2. <br>            new FileSystemXmlApplicationContext("applicationContext.xml");  
  3. <br>        UserDAOImpl userDAOImpl =   
  4. <br>            (UserDAOImpl)ctx.getBean("userDAOProxy");  
  5. <br>        userDAOImpl.save();  

   上面这样的情况下程序能够正常执行,可是假设UserDAOImpl实现了一个接口,其它不变

  1. public class UserDAOImpl implements UserDAO {  
  2. <br>  
  3. <br>    public void save() {  
  4. <br>        // TODO Auto-generated method stub  
  5. <br>        System.out.println("user saved");  
  6. <br>    }  
  7. <br>  
  8. <br>}  

 这样的情况下,程序将不能正常执行,会抛出java.lang.ClassCastException异常

理解上面这样的情况产生的原因须要了解Spring AOP的实现原理。


Spring 实现AOP是依赖JDK动态代理和CGLIB代理实现的。


下面是JDK动态代理和CGLIB代理简介
    JDK动态代理:其代理对象必须是某个接口的实现。它是通过在执行期间创建一个接口的实现类来完毕对目标对象的代理。


    CGLIB代理:实现原理类似于JDK动态代理,仅仅是它在执行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比JDK强。


Spring是依靠什么来推断採用哪种代理策略来生成AOP代理呢?下面代码就是Spring的推断逻辑

 

 

 

 

 

         advisedSupport.isOptimize()与advisedSupport.isProxyTargetClass()默认返回都是false,所以在默认情况下目标对象有没有实现接口决定着Spring採取的策略。当然能够设置advisedSupport.isOptimize()或者advisedSupport.isProxyTargetClass()返回为true。这样不管目标对象有没有实现接口Spring都会选择使用CGLIB代理。所以在默认情况下,假设一个目标对象假设实现了接口Spring则会选择JDK动态代理策略动态的创建一个接口实现类(动态代理类)来代理目标对象。能够通俗的理解这个动态代理类是目标对象的另外一个版本号。所以这两者之间在强制转换的时候会抛出j ava.lang.ClassCastException。而所以在默认情况下,假设目标对象没有实现不论什么接口,Spring会选择CGLIB代理, 其生成的动态代理对象是目标类的子类。

 

 

   

     以上说的是默认情况下。也能够手动配置一些选项使Spring採用CGLIB代理。

org.springframework.transaction.interceptor.TransactionProxyFactoryBean是org.springframework.aop.framework. ProxyConfig的子类,所以能够參照ProxyConfig里的一些设置例如以下所看到的,将optimize和proxyTargetClass随意一个设置为true都能够强制Spring採用CGLIB代理。

  1. //相关配置,省略了一些不相关内容  
  2. <br><bean id="userDAO" class="UserDAOImpl">  
  3. <br><bean id="userDAOProxy"  class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">   
  4. <br>    <property name="target">   
  5. <br>        <ref local="userDAO" />   
  6. <br>    </property>   
  7. <br>    <property name="optimize">   
  8. <br>        <value>true</value>  
  9. <br>    </property>  
  10. <br>    <property name="proxyTargetClass">   
  11. <br>        <value>true</value>  
  12. <br>    </property>   
  13. <br></bean>  

 

 

使用CGLIB代理也就不会出现前面提到的ClassCastException问题了,

也能够在性能上有所提高,可是也有它的弊端,Spring doc原文解释例如以下optimization will usually mean that advice changes won't take effect after a proxy has been created. For this reason, optimization  is disabled by default。





本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5177571.html,如需转载请自行联系原作者

相关文章
|
1月前
|
Java 程序员 Linux
IT圈的“鄙视链”大揭秘:从Java到Go,编程语言之战!
IT圈的“鄙视链”大揭秘:从Java到Go,编程语言之战!
java.lang.Error: Unresolved compilation problem: The type List is not generic; it cannot be parame
java.lang.Error: Unresolved compilation problem: The type List is not generic; it cannot be parame
|
23小时前
|
安全 Java API
java借助代理ip,解决访问api频繁导致ip被禁的问题
java借助代理ip,解决访问api频繁导致ip被禁的问题
|
1月前
|
Java API 开发者
Java代理模式——静态代理与动态代理
Java代理模式——静态代理与动态代理
26 1
|
1月前
|
监控 Java 程序员
java的动态代理如何实现
java的动态代理如何实现
24 0
|
2月前
|
设计模式 Java 程序员
Java动态代理
Java动态代理详解
|
2月前
|
Java
Java动态代理简易说明
Java动态代理简易说明
10 0
|
2月前
|
设计模式 Java API
[Java]静态代理、动态代理(基于JDK1.8)
本篇文章主要是对静态代理和动态代理实现思路的简述,以示例为主,少涉及理论。 如果文中阐述不全或不对的,多多交流。
54 1
[Java]静态代理、动态代理(基于JDK1.8)
|
3月前
|
设计模式 Java
java中的jdk代理和cglib代理
在Java中,代理是一种设计模式,它允许一个对象(代理)控制对另一个对象(真实对象)的访问。Java中的代理主要分为两种类型:JDK(Java Dynamic Proxy)代理和CGLIB(Code Generation Library)代理。