Spring AOP應用場景你還不知道?這篇一定要看!

  • 2019 年 10 月 5 日
  • 筆記

回顧一下Spring AOP的知識

為什麼會有面向切面編程(AOP)?

我們知道Java是一個面向對象(OOP)的語言,但它有一些弊端,比如當我們需要為多個不具有繼承關係的對象引入一個公共行為,例如日誌、權限驗證、事務等功能時,只能在在每個對象里引用公共行為。這樣做不便於維護,而且有大量重複代碼。AOP的出現彌補了OOP的這點不足。

Spring AOP 中設計的一些核心知識,面試問題?

1、能說一下Spring AOP用的是哪種設計模式?

回答:代理模式。

2、 能簡單聊一下你對代理模式的理解嗎?

代理模式 balabala……,記住一些貼近日常的示例方便理解,如買火車票,Windows 裏面的快捷方式…

3、 知道JDK代理和Cglib代理有什麼區別?

我們不需要創建代理類,JDK 在運行時為我們動態的來創建,JDK代理是接口 balabala

若目標類不存在接口,則使用Cglib生成代理,balabala

不管是JDK代理還是Cglib代理本質上都是對位元組碼進行操作,balabala

4、讓你實現一個JDK實現動態代理?你的思路是什麼?

照葫蘆畫瓢,照貓畫虎。

Proxy: 定義一個自己的Proxy類

InvocationHandler:定義一個自己的InvocationHandler類

ClassLoad:自定義類加載器(方便加載我們自己指定的路徑下面的類)

上面簡單回顧,並拋出一些問題。帶着問題閱讀,效果杠杠的。

回到本文的重點

SpringAOP的在實際應用中場景有哪些?

  1. Authentication 權限
  2. Caching 緩存
  3. Context passing 內容傳遞
  4. Error handling 錯誤處理
  5. Lazy loading 懶加載
  6. Debugging 調試
  7. logging,tracing,profiling and monitoring 記錄跟蹤 優化 校準
  8. Performance optimization 性能優化
  9. Persistence 持久化
  10. Resource pooling 資源池
  11. Synchronization 同步
  12. Transactions 事務
  13. Logging 日誌

以日誌為例

假如沒有aop,在做日誌處理的時候,我們會在每個方法中添加日誌處理,比如

但大多數的日子處理代碼是相同的,為了實現代碼復用,我們可能把日誌處理抽離成一個新的方法。但是這樣我們仍然必須手動插入這些方法。

但這樣兩個方法就是強耦合的,假如此時我們不需要這個功能了,或者想換成其他功能,那麼就必須一個個修改。

通過動態代理,可以在指定位置執行對應流程。這樣就可以將一些橫向的功能抽離出來形成一個獨立的模塊,然後在指定位置

插入這些功能。這樣的思想,被稱為面向切面編程,亦即AOP。

為了在指定位置執行這些橫向的功能,需要知道指定的是什麼地方。

例如上圖,方法級別的aop實現,在一個程序執行鏈條中,把method2稱為切點,也就是說在method2執行時會執行橫切的功能,那麼是在method2之前還是之後呢,又是執行什麼呢?這些都由advice(通知)來指定。advice有5種類型,分別是:

  • Before(前置通知) 目標方法調用之前執行
  • After(後置通知) 目標方法調用之後執行
  • After-returning(返回通知) 目標方法執行成功後執行
  • After-throwing(異常通知) 目標方法拋出異常後執行
  • Around(環繞通知) 相當於合併了前置和後置

把切點和通知合在一起就是切面了,一個切面指定了在何時何地執行何種方法。在spring aop中如此定義這個切面:

@Aspect  @Component  public class HelloAspect {      @Before("execution(* com.test.service.impl.HelloServiceImpl.sayHello(..))")    public void sayHello(){      System.out.println("hello Java編程技術樂園!");    }    }

使用註解@Aspect將某個特定的類聲明為切面,這樣,該類下的方法就可以聲明為橫向的功能點後插入到指定位置。使用execution表達式聲明在這個切點,格式如下:

第一個位置指定了方法的返回值,*號代表任意類型的返回值,然後是所在的類和方法名,星號同樣代表任意,就是該類中任意的方法,在上一個例子中方法名是sayHello,則是指定了該類中的sayHello方法。然後最後一個參數是方法入參,因為Java中支持重載,所以這個參數可以幫助你更精確的進行定位。兩點表示任意參數類型。這樣,execution表達式告訴了程序該在何地執行通知。而被諸如@Before註解修飾的方法就是通知的內容,也就是做什麼。

總結

我們使用spring aop,有兩點需要注意:

1、將切面類聲明為一個bean

2、切點指定的方法所在的類也同樣需由spring注入才能生效 歡迎大家關注我的公種浩【程序員追風】,文章都會在裏面更新,整理的資料也會放在裏面。 最後 歡迎大家一起交流,喜歡文章記得點個贊喲,感謝支持!