Spring框架的AOP機制

AOP是Spring框架面向切面的編程思想,AOP採用一種稱爲“橫切”的技術,將涉及多業務流程的通用功能抽取並單獨封裝,形成獨立的切面,在合適的時機將這些切面橫向切入到業務流程指定的位置中。本篇結合實際案例詳細講述AOP的原理及實現過程。通過本篇的學習,可以達成如下目標。

● 理解AOP的編程思想及原理

● 掌握AOP的實現技術

Spring框架的AOP機制可以讓開發者把業務流程中的通用功能抽取出來,單獨編寫功能代碼。在業務流程執行過程中,Spring框架會根據業務流程要求,自動把獨立編寫的功能代碼切入到流程的合適位置。

例如,在一個業務系統中,用戶登錄是基礎功能,凡是涉及到用戶的業務流程都要求用戶進行系統登錄。如果把用戶登錄功能代碼寫入到每個業務流程中,會造成代碼冗餘,維護也非常麻煩,當需要修改用戶登錄功能時,就需要修改每個業務流程的用戶登錄代碼,這種處理方式顯然是不可取的。比較好的做法是把用戶登錄功能抽取出來,形成獨立的模塊,當業務流程需要用戶登錄時,系統自動把登錄功能切入到業務流程中。下圖是用戶登錄功能切入到業務流程示意圖。

圖1 用戶登錄功能切入到業務流程示意圖

1、 一個AOP案例描述

在課程案例SpringProgram項目中,一個業務流程是校長通過郵件發送上課通知給老師。校長執行該業務時,業務系統並沒有對老師進行驗證。現在要求校長在發送通知之前,需要對老師進行用戶驗證。

具體要求是在儘量不改變原有業務代碼的情況下,加入老師驗證功能。原有業務代碼如下。

EmailNotice業務類代碼沒有對老師身份進行驗證,可以考慮在執行setTeacher方法之前執行驗證功能。

具體的操作步驟是:

(1)添加老師身份驗證功能代碼,用於切入到EmailNotice業務類,身份驗證功能代碼也稱爲切面,切入點爲EmailNotice業務類的setTeacher方法;

(2)在Spring配置文件中配置AOP,添加切入面、切入點以及需要切入的目標Bean;

(3)編寫測試代碼,測試程序運行地正確性。

2、 實現AOP案例代碼

在實現AOP案例之前,需要確定項目已經引入了Spring框架關於AOP功能的Jar包。下面列出的是spring-aop-5.0版本,其它版本也可以。

● spring-aop-5.0.8.RELEASE

● spring-aspects-5.0.8.RELEASE

另外還需要引入下面的Jar包:

● aspectjrt

● aspectjweaver

在課程案例SpringProgram項目中,相關的Teacher實體類、EmailNotice業務類、Spring配置文件已經存在,爲了不影響前面課程的案例。實現AOP的代碼重新編寫AopTeacher實體類、AopEmailNotice業務類以及Spring配置文件。

(1)添加AopTeacher實體類

在課程案例SpringProgram項目中,添加AopTeacher實體類。

(2)添加老師身份驗證功能

在課程案例SpringProgram項目中,添加VerifyUser類,並添加類方法beforeAdvice,該方法需要傳入AopTeacher實體類,用於驗證老師身份的合法性。

(3)添加AopEmailNotice業務類

在課程案例SpringProgram項目中,添加AopEmailNotice業務類。

AopEmailNotice業務類內置了AopTeacher對象,並通過sendMessage方法發送通知給AopTeacher對象。setTeacher方法用於設置AopTeacher對象,在設置之前需要驗證AopTeacher對象身份的合法性,也就是要在setTeacher方法執行之前,執行VerifyUser類的beforeAdvice方法。

(4)添加Spring配置文件

在課程案例SpringProgram項目中,添加Spring配置文件aop.xml。

aop.xml需要使用AOP命名空間,因此需要在配置文件中導入spring-aop架構,添加下面的AOP命名空間。

標籤用於AOP創建代理切入類(代理類)是基於接口的還是基於類的,如果proxy-target-class 屬性值被設置爲true,那麼創建基於類的代理,否則創建基於接口的代理。

標籤用於配置AOP。其中子標籤添加一個切面Aspect,一個切面可以是一個模塊或一個類。例如驗證用戶身份的VerifyUser類,該切面將被AOP調用。可以配值多個切面。

標籤用於聲明一個切入點,也就是切面提供的哪些方法可以被調用。expression 爲切入點的表達式,用於定義切入點的路徑。

例如:

execution(* com.milihua.springprogram.notice.AopEmailNotice.setTeacher(..))

上述表達式的意思是切入點爲AopEmailNotice的setTeacher方法。其中*號表示切入點爲任意的返回類型,(..)表示任意參數。

再如:

execution(* com.milihua.springprogram.notice. .*.*(..))

上述表達式的意思是切入點爲com.milihua.springprogram.notice包及子包下所有的類及類中所有的方法。

又如:

execution(* com.milihua.springprogram.notice. *.*(..))

上述表達式的意思是切入點爲com.milihua.springprogram.notice包下所有的類及類中所有的方法。

(5)編寫測試代碼

在課程案例SpringProgram項目中,添加AopTest測試類。

測試程序運行結果如下圖所示。

 

3、AOP編程思想及術語

AOP是面向切面的編程,其編程思想是把散佈於不同業務但功能相同的代碼從業務邏輯中抽取出來,封裝成獨立的模塊,這些獨立的模塊被稱爲切面,切面的具體功能方法被稱爲關注點。在業務邏輯執行過程中,AOP會把分離出來的切面和關注點動態切入到業務流程中,這樣做的好處是提高了功能代碼的重用性和可維護性。

例如,前面案例的VerifyUser類就是切面,VerifyUser類的beforeAdvice就是關注點。VerifyUser切面的功能就是驗證老師身份,可以應用到與老師相關的不同業務流程中。AopEmailNotice是一個業務類,負責發送通知給老師,在發送通知之前需要驗證老師的身份。AOP會在AopEmailNotice類的setTeacher方法執行之前,將beforeAdvice關注點切入到AopEmailNotice業務類中,並執行beforeAdvice方法。

Spring框架提供了@AspectJ 註解方法和基於XML架構的方法來實現AOP。前面的案例是基於XML架構的方法,後面一節會講述基於@AspectJ 註解的方法。下面結合前面的案例講述一下AOP的相關術語。

● Aspect

表示切面。切入業務流程的一個獨立模塊。例如,前面案例的VerifyUser類,一個應用程序可以擁有任意數量的切面。

● Join point

表示連接點。也就是業務流程在運行過程中需要插入切面的具體位置。例如,前面案例的AopEmailNotice類的setTeacher方法就是一個連接點。

● Advice

表示通知。是切面的具體實現方法。可分爲前置通知(Before)、後置通知(AfterReturning)、異常通知(AfterThrowing)、最終通知(After)和環繞通知(Around)五種。實現方法具體屬於哪類通知,是在配置文件和註解中指定的。例如,VerifyUser類的beforeAdvice方法就是前置通知。

● Pointcut

表示切入點。用於定義通知應該切入到哪些連接點上,不同的通知通常需要切入到不同的連接點上。例如,前面案例配置文件的<aop:pointcut>標籤。

● Target

表示目標對象。被一個或者多個切面所通知的對象。例如,前面案例的AopEmailNotice類。

● Proxy

表示代理對象。將通知應用到目標對象之後被動態創建的對象。可以簡單地理解爲,代理對象爲目標對象的業務邏輯功能加上被切入的切面所形成的對象。

● Weaving

表示切入,也稱爲織入。將切面應用到目標對象從而創建一個新的代理對象的過程。這個過程可以發生在編譯期、類裝載期及運行期。

課程小結

(1)本篇探討了AOP的編程思想,其主要思想是讓開發者把諸多業務流程中的通用功能抽取出來,單獨編寫功能代碼,形成獨立的模塊,這些模塊也被稱爲切面。在業務流程執行過程中,Spring框架會根據業務流程要求,自動把切面切入到流程的合適位置。

(2)本篇也通過案例講述了AOP的實現過程,具體實現步驟是:首先編寫需要切入業務流程的獨立模塊(也稱爲切面)和切入點(模塊中的方法);然後在Spring配置文件中配置AOP,添加切入面、切入點以及需要切入的目標Bean;最後編寫測試代碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章