[攔截器]關於攔截方法調用其他內部方法無法被攔截問題的解決(轉)


原文 https://blog.csdn.net/quzishen/article/details/5803721

攔截器的實現原理很簡單,就是動態代理,實現AOP機制。當外部調用被攔截bean的攔截方法時,可以選擇在攔截之前或者之后等條件執行攔截方法之外的邏輯,比如特殊權限驗證,參數修正等操作。但是如果現在一個需求是,當外部調用攔截bean的時候,不但要執行攔截當前方法,如果當前方法內部同時調用了其他內部方法,也要被攔截。按照目前的攔截器實現邏輯,是無法攔截當前方法內部調用的方法的,這樣說有點抽象,看一個代碼:

 

[java]  view plain  copy
 
  1. public class BeanA{  
  2. public void method1(){  
  3. method2();  
  4. }  
  5. public void method2(){  
  6. ...  
  7. }  
  8. }  

 

 

當外部調用beanA.method1();的時候,攔截器執行攔截邏輯,執行完畢后進入method1方法執行,當調用method2的時候,攔截器是否會再次攔截?是不會的,這里涉及到攔截器的一個原理,攔截器涉及兩個對象,代理對象和原始對象,攔截器所執行的代理對象執行完畢后,當執行method1即進入了原始對象,那么在原始對象中調用method2,是無法進行攔截的。所以很顯眼,這樣無法滿足我們的需求。

在spring的源代碼中通過一個增強對象的檢查,控制了當前的內部調用是否使用代理來執行,這讓人感到無奈。spring的作者們很隱晦的提出避免內部調用的方法。

我們可能會想,在外部調用兩次beanA,第一次調用method1,第二次調用method2,這樣做可以解決問題,但是這樣的直接后果是我們的邏輯代碼將變得紊亂,並非所有的場景下都可以通過這樣的設計來完成。雖然這是spring官方推薦的避免內部調用的idea。

查看了相關資料,得到了一種方法,即在method1的內部,通過直接獲取當前代理對象的方式然后通過代理對象調用method2,這樣觸發攔截。

看看代碼:

 

[java]  view plain  copy
 
  1. public void method1(){  
  2.         logger.error("1");  
  3.           
  4.         // 如果希望調用的內部方法也被攔截,那么必須用過上下文獲取代理對象執行調用,而不能直接內部調用,否則無法攔截  
  5.         if(null != AopContext.currentProxy()){  
  6.             ((NorQuickNewsDAO)AopContext.currentProxy()).method2();  
  7.         }else{  
  8.             method2();  
  9.         }         
  10.     }  
  11.       
  12.     public void method2(){  
  13.         logger.error("2");  
  14.     }  

 

 

我們顯示的調用了AopContext來獲取當前代理對象,然后調用其方法,這樣做還必須的一個步驟是將當前的代理暴露給線程使用,在配置文件中需要配置一個參數:

 

[xhtml]  view plain  copy
 
  1. <property name="exposeProxy">  
  2.             <value>true</value>  
  3.         </property>  

 

 

它是ProxyConfig的一個參數,默認是false,如果不設置這個參數,那么上述java代碼將無法獲取當前線程中的代理對象。

這種方法可以成功觸發攔截,但是也帶來了其他問題,比如代碼的織入,我們的代碼將變得復雜而且晦澀,而且嚴格要求系統針對於當前的bean必須配置攔截器,否則會因為找不到攔截器而拋出異常。

這樣做有什么負面影響?對事務的影響,對安全的影響,現在不得而知,還需要逐步去測試以嘗試。

 

PS: 此文已經說明了嵌套攔截失效的理由,我的另外一篇文章提供了一種相對無縫的處理方案

http://www.cnblogs.com/devilwind/p/8724483.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM