1 AOP的簡介
AOP最早是由AOP聯盟的組織提出的一種思想,而Spring是AOP實現的最好的一個框架,並不是AOP是Spring創造出來的。
Spring最早的AOP是有自己的實現方式,但是非常繁瑣,後來吸收了一個AOP開源框架AspectJ作爲自身AOP的開發。
Spring的AOP開發有兩套開發方式
- Spring的傳統方式(非常繁瑣,被棄用了)
- Spring基於AspectJ的AOP開發(正在使用)
爲什麼要AOP:(1)賴,一次開發,多次可用(如日誌記錄、事務管理等功能的實現)(2)爲了更清晰的邏輯,可以讓你的業務邏輯去關注自己本身的業務,而不去想一些其他的事情,這些其他的事情包括:安全,事物,日誌等。
2 AOP的術語
- 通知(Advice)
就是你想要的功能,也就是上面說的 安全,事物,日誌等。你給先定義好把,然後在想用的地方用一下。(方法層面的增強)
2.連接點(JoinPoint)
可以被攔截到的點:這個更好解釋了,就是spring允許你使用通知的地方,那可真就多了,基本每個方法的前,後(兩者都有也行),或拋出異常時都可以是連接點,spring只支持方法連接點.其他如aspectJ還可以讓你在構造器或屬性注入時都行,不過那不是咱關注的,只要記住,和方法有關的前前後後(拋出異常),都是連接點。
3.切入點(Pointcut)
真正被攔截到的點:上面說的連接點的基礎上,來定義切入點,你的一個類裏,有15個方法,那就有幾十個連接點了對把,但是你並不想在所有方法附近都使用通知(使用的過程叫織入,後面再說),你只想讓其中的幾個,在調用這幾個方法之前,之後或者拋出異常時乾點什麼,那麼就用切點來定義這幾個方法,讓切點來篩選連接點,選中那幾個你想要的方法。
4.切面(Aspect)
切面=多個通知+切入點。通知說明了幹什麼和什麼時候幹(什麼時候通過方法名中的before,after,around等就能知道),而切入點說明了在哪幹(指定到底是哪個方法),這就是一個完整的切面定義。(現在發現了吧,沒連接點什麼事情,連接點就是爲了讓你好理解切入點,搞出來的,明白這個概念就行了)
5.引入(introduction)
允許我們向現有的類添加新方法屬性。這不就是把切面(也就是新方法屬性:通知定義的)用到目標類中嗎。(類層面的增強)
6.目標(target)
引入中所提到的目標類,也就是要被通知的對象,也就是真正的業務邏輯,他可以在毫不知情的情況下,被咱們織入切面。而自己專注於業務本身的邏輯。
7.織入(weaving)
把切面應用到目標對象來創建新的代理對象的過程。有3種方式,spring採用的是運行時。(爲什麼是運行時,上一篇文章springAOP的實現原理有解釋)
8.代理(proxy)
切面應用到目標對象來創建的新的代理對象。怎麼實現整套aop機制的,都是通過代理。
3 AOP的XML開發
從上面的術語介紹來看,要想做AOP開發得有三步
* 有目標(target)和切入點(Pointcut)
* 有通知(Advice)
* 將通知織入(weaving)目標中的切入點得到切面(Aspect)
第一步: 編寫目標和切入點
我們以一個UserDaoImpl類爲例,實現將簡單的增刪查改
第二步:編寫容納通知的切面類及通知
第三步:配置XML文件進行織入
4 通知的類型
4.1 前置通知:在方法前通知
<aop:before method="checkPri" pointcut-ref="pointcut1"/>
4.2 後置通知:在方法後通知
注:可以獲得方法的返回值,但是returning的值必須和通知的入參Object是一樣的(樣例中爲result)
<aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"/>
4.3 環繞通知
注:可以控制原方法是否執行
<aop:around method="around" pointcut-ref="pointcut3" />
4.4 異常拋出通知
注:可以獲得異常信息,但通知的入參必須爲Throwable類,且名字和配置的throwing相同(樣例中爲ex)
<aop:after-throwing method="afterException" pointcut-ref="pointcut4" throwing="ex"/>
4.5 最終通知:等同於finally
<aop:after method="after" pointcut-ref="pointcut4"/>
4.6 引介通知(不用會)
applicationContext.xml
MyAspectXML.java
5 切入點表達式語法
- 基於execution的函數完成
- 語法
- [訪問修飾符] 方法返回值 包名.類名.方法名(參數)
- 樣例:public void com.hy.spring.CustomerDao.save(..)
- * com.hy.spring.CustomerDao.*(..) :任意地方都可以使用 * 代表通用
- *.com.hy.spring.CustomerDao+.save(..):+代表該類及其子類
- * com.hy.spring..*.*(..):兩個點代表該包及其子包
6 AOP的註解開發
在aop的xml方式開發中,我們將開發步驟分爲了三步:
* 有目標(target)和切入點(Pointcut)
* 有通知(Advice)
* 將通知織入(weaving)目標中的切入點得到切面(Aspect)
同樣的,在aop的註解開發時,我們同樣分爲這三步
第一步:編寫目標和切入點
這裏我們用直接用一個CustomerDao作爲目標實現。
第二步:編寫通知
這裏我們在一個名爲MyAspectAnno的切面類中編寫前置、後置、異常拋出等等通知。(後面會貼出具體實現)
第三步:配置切面類,進行織入
如下圖,我們通過註解,配置了切面類、切入點、各種通知以及切入點和通知之間的聯繫