Spring AOP底層原理及代理模式
Spring AOP底層原理代理模式
一、什麼是 AOP
AOP 就是面向切面編程,是 OOP(面向對象編程)的延續。
利用 AOP 可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程序可用性,同時也提高瞭開發效率。
通俗一點說,不用修改原代碼,可以給原代碼增加新的功能。
二、AOP 底層原理
AOP 底層原理是使用動態代理。
那代理是什麼?有動態代理,那是不是還有靜態代理?
1. 什麼是代理?
就是為一個目標對象提供一個代理對象,並由代理對象控制對目標對象的引用。使用代理對象,是為瞭在不修改目標對象的基礎上,增強目標對象的業務邏輯。
比如目標對象 A,代理對象是 B。
- 那麼現在 B 對 A 進行引用,可以實現 A 有的功能。
- 另外,B 還可以在自身進行一些新功能,最終不需要修改目標對象 A 。
而代理分為靜態代理和動態代理,區別是:
靜態代理有真實的代理類存在,就是我們會代碼中創建一個代理類,並在代理類的方法中調用目標對象的方法,以此來完成代理的工作。動態代理的代理類沒有在代碼中創建一個代理類,而是在運行時在JVM裡面創建代理對象。
2. 什麼是靜態代理
靜態代理是有實實在在的代理類存在,並且和目標類實現相同的接口。
比如,有一個轉賬業務,現在希望給它增加功能,使在轉賬之前確認轉賬人身份,以及轉賬之後通知收款人。
(1) 接口 AccountServiceDao :
package com.pingguo.spring5.dao; public interface AccountServiceDao { // 主業務邏輯,轉賬 void transfer(); }
(2) 接口 AccountServiceDao 的實現類:
package com.pingguo.spring5.dao; public class AccountServiceImpl implements AccountServiceDao { @Override public void transfer() { System.out.println("調用dao層,完成轉賬主業務."); } }
(3) 代理類 AccountProxy :
package com.pingguo.spring5.proxy; import com.pingguo.spring5.dao.AccountServiceDao; public class AccountProxy implements AccountServiceDao { // 目標對象 private AccountServiceDao target; public AccountProxy(AccountServiceDao target) { this.target = target; } /** * 代理方法,實現對目標方法的增強 */ @Override public void transfer() { before(); target.transfer(); after(); } /** * 增強的功能,轉賬之前使用 */ private void before() { System.out.println("對轉賬人身份進行驗證."); } /** * 增強的功能,轉賬之後使用 */ private void after() { System.out.println("轉賬完成,已通知收款人."); } }
在代理類中:
- 添加瞭添加瞭目標對象,並且有參構造方法裡需要傳入目標對象。
- 代理方法裡,調用瞭目標對象裡的轉賬方法 target.transfer()。
- before() 和 after() 則是 2個增強的方法,分別作用於 target.transfer() 的前面和後面。
(4) 運行測試新建一個測試方法,運行看下結果:
@Test public void testProxy() { // 創建目標對象 AccountServiceDao target = new AccountServiceImpl(); // 創建代理對象 AccountProxy proxy = new AccountProxy(target); proxy.transfer(); }
- 這裡先創建瞭目標對象
- 再創建代理對象,並且把目標對象傳入
- 最後調用代理對象裡的,被增強過的方法 transfer()。
結果:
對轉賬人身份進行驗證. 調用dao層,完成轉賬主業務. 轉賬完成,已通知收款人. Process finished with exit code 0
優點:
- 效率高,因為所有的類都是已經編寫完成的,使用的時候隻需要取得代理對象並且執行即可。
- 同時也可以實現對目標對象中指定的方法進行增強。
缺點:
- 與目標類實現相同的接口代碼,冗餘。
- 如果接口發生改變,代理類中的方法也要修改。
- 代理類服務於一種類型的對象,如果要服務多類型的對象,那麼要為每種類型的對象都生成代理類。
3. 什麼是動態代理
與靜態代理的硬編碼方式相比,動態代理支持運行時動態生成代理對象這種方式。換句話說,動態代理並不存在代理類,代理對象直接由代理生成工具動態生成。
優點:
- 用很少的代碼對一個類的所有方法實現一樣的增強效果。
- 在編碼時,代理邏輯與業務邏輯互相獨立,各不影響,減少侵入,降低耦合。
缺點:
相對於靜態代理,它不能增強其中的某一個方法。
對於動態代理,針對於是否存在接口的情況下,又分為 2 種:
- 有接口的情況下,使用 JDK 動態代理。
- 無接口的情況下,使用 CGLIB 動態代理。
使用 JDK 動態代理
使用 JDK 動態代理,創建的是接口實現類的代理對象,以此來實現功能增強。
現在不需要上面創建過的實際代理類瞭 。
接口,為瞭後面的一些知識點的說明,裡面加個參數,轉賬的金額:
package com.pingguo.spring5.dao; public interface AccountServiceDao { // 主業務邏輯,轉賬 void transfer(int amount); }
實現類:
package com.pingguo.spring5.dao; public class AccountServiceImpl implements AccountServiceDao { @Override public void transfer(int amount) { System.out.println("調用dao層,完成轉賬主業務.金額:" + amount); } }
在測試方法裡,直接使用動態代理:
@Test public void testDynamicProxy() { // 創建目標對象 AccountServiceDao target = new AccountServiceImpl(); // 創建代理對象 AccountServiceDao proxy = (AccountServiceDao) Proxy.newProxyInstance( target.getClass().getClassLoader(), // 目標類使用的類加載器 target.getClass().getInterfaces(), // 目標類實現的接口 new InvocationHandler() { // 調用處理器 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("對轉賬人身份進行驗證."); Object res = method.invoke(target, args); System.out.println("轉賬完成,已通知收款人."); return res; } } ); // 讓代理工作 proxy.transfer(10000); }
運行結果:
對轉賬人身份進行驗證. 調用dao層,完成轉賬主業務.金額:10000 轉賬完成,已通知收款人. Process finished with exit code 0
動態代理的過程:
- 創建處理器 InvocationHandler實例。
- 在調用目標對象時,會調用代理對象。
- 代理對象去請求目標對象。invoke 方法就是調用目標對象的方法生成代理對象的過程。
- 同時,在 invoke 方法中進行功能增強。
對於 invoke 中的 3 個參數,分別是:
- Object proxy:代理對象,一般不會使用。
- Method method:外面的代理對象調用的方法引用,這裡引用的就是 transfer()
- Object[] args:外面的代理對象調用的方法裡面的參數,這裡就是參數 amount。
使用 CGLIB 動態代理
CGLIB動態代理的原理是生成目標類的子類,這個子類對象就是代理對象,代理對象是被增強過的。
註意,不管有沒有接口都可以使用 CGLIB 動態代理, 而不是隻有在無接口的情況下才能使用。
示例就暫時不放瞭,因為我本地環境問題,有個報錯始終未解決,後續再說,不影響繼續學習 spring。
以上就是Spring AOP底層原理及代理模式的詳細內容,更多關於Spring AOP底層原理的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- 帶你深入瞭解java-代理機制
- Spring中AOP概念與兩種動態代理模式原理詳解
- 解析動態代理jdk的Proxy與spring的CGlib(包括區別介紹)
- Java的三種代理模式簡述
- Spring AOP的底層實現方式-代理模式