IT忍者神龜之Java動態代理與CGLib代理,忍者神龜cglib

來源:互聯網
上載者:User

IT忍者神龜之Java動態代理與CGLib代理,忍者神龜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是依靠什麼來判斷採用哪種Proxy 原則來產生AOP代理呢?以下代碼就是Spring的判斷邏輯

 

 

 

 

 

         advisedSupport.isOptimize()與advisedSupport.isProxyTargetClass()預設返回都是false,所以在預設情況下目標對象有沒有實現介面決定著Spring採取的策略,當然可以設定advisedSupport.isOptimize()或者advisedSupport.isProxyTargetClass()返回為true,這樣無論目標對象有沒有實現介面Spring都會選擇使用CGLIB代理。所以在預設情況下,如果一個目標對象如果實現了介面Spring則會選擇JDK動態Proxy 原則動態建立一個介面實作類別(動態代理類)來代理目標對象,可以通俗的理解這個動態代理類是目標對象的另外一個版本,所以這兩者之間在強制轉換的時候會拋出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。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.