面向對象程式設計(OOP)的好處是顯而易見的,缺點也同樣明顯。當需要為多個不具有繼承關系的對象添加一個公共的方法的時候,例如日志記錄、性能監控等,如果采用面向對象程式設計的方法,需要在每個對象裡面都添加相同的方法,這樣就産生了較大的重複工作量和大量的重複代碼,不利于維護。面向切面程式設計(AOP)是面向對象程式設計的補充,簡單來說就是統一處理某一“切面”的問題的程式設計思想。如果使用AOP的方式進行日志的記錄和處理,所有的日志代碼都集中于一處,不需要再每個方法裡面都去添加,極大減少了重複代碼。
通知(Advice)包含了需要用于多個應用對象的橫切行為,完全聽不懂,沒關系,通俗一點說就是定義了“什麼時候”和“做什麼”。
連接配接點(Join Point)是程式執行過程中能夠應用通知的所有點。
切點(Poincut)是定義了在“什麼地方”進行切入,哪些連接配接點會得到通知。顯然,切點一定是連接配接點。
切面(Aspect)是通知和切點的結合。通知和切點共同定義了切面的全部内容——是什麼,何時,何地完成功能。
引入(Introduction)允許我們向現有的類中添加新方法或者屬性。
織入(Weaving)是把切面應用到目标對象并建立新的代理對象的過程,分為編譯期織入、類加載期織入和運作期織入。
Spring Boot使用AOP需要添加spring-boot-starter-aop依賴,如下:
不需要再添加aspectjweaver的依賴了,因為spring-boot-starter-aop包含了aspectjweaver,并且版本是較新的版本,如果在添加老版本(如1.5.4)啟動會報錯。
直接定義一個controller,代碼如下:
Spring采用@AspectJ注解對POJO進行标注,該注解表明該類不僅僅是一個POJO,還是一個切面。切面是切點和通知的結合,那麼定義一個切面就需要編寫切點和通知。在代碼中,隻需要添加@Aspect注解即可。
切點是通過@Pointcut注解和切點表達式定義的。
@Pointcut注解可以在一個切面内定義可重用的切點。
由于Spring切面粒度最小是達到方法級别,而execution表達式可以用于明确指定方法傳回類型,類名,方法名和參數名等與方法相關的部件,并且實際中,大部分需要使用AOP的業務場景也隻需要達到方法級别即可,因而execution表達式的使用是最為廣泛的。如圖是execution表達式的文法:
execution表示在方法執行的時候觸發。以“”開頭,表明方法傳回值類型為任意類型。然後是全限定的類名和方法名,“”可以表示任意類和任意方法。對于方法參數清單,可以使用“..”表示參數為任意類型。如果需要多個表達式,可以使用“&&”、“||”和“!”完成與、或、非的操作。
通知有五種類型,分别是:
前置通知(@Before):在目标方法調用之前調用通知
後置通知(@After):在目标方法完成之後調用通知
環繞通知(@Around):在被通知的方法調用之前和調用之後執行自定義的方法
傳回通知(@AfterReturning):在目标方法成功執行之後調用通知
異常通知(@AfterThrowing):在目标方法抛出異常之後調用通知
代碼中定義了三種類型的通知,使用@Before注解辨別前置通知,列印“beforeAdvice...”,使用@After注解辨別後置通知,列印“AfterAdvice...”,使用@Around注解辨別環繞通知,在方法執行前和執行之後分别列印“before”和“after”。這樣一個切面就定義好了,代碼如下:
完成之後的代碼結構如圖所示:
運作AopApplication,在浏覽器通路http://localhost:8080/hello,不出意外,控制台輸出如圖所示:
由于部落客也是在攀登的路上,文中可能存在不當之處,歡迎各位多指教! 如果文章對您有用,那麼請點個”推薦“,以資鼓勵!