Spring Boot使用AOP的正確姿式

1、爲何須要面向切面編程?

面向對象編程(OOP)的好處是顯而易見的,缺點也一樣明顯。當須要爲多個不具備繼承關係的對象添加一個公共的方法的時候,例如日誌記錄、性能監控等,若是採用面向對象編程的方法,須要在每一個對象裏面都添加相同的方法,這樣就產生了較大的重複工做量和大量的重複代碼,不利於維護。面向切面編程(AOP)是面向對象編程的補充,簡單來講就是統一處理某一「切面」的問題的編程思想。若是使用AOP的方式進行日誌的記錄和處理,全部的日誌代碼都集中於一處,不須要再每一個方法裏面都去添加,極大減小了重複代碼。spring

2、Spring AOP術語

Spring AOP術語

通知(Advice)包含了須要用於多個應用對象的橫切行爲,徹底聽不懂,不要緊,通俗一點說就是定義了「何時」和「作什麼」。編程

鏈接點(Join Point)是程序執行過程當中可以應用通知的全部點。瀏覽器

切點(Poincut)是定義了在「什麼地方」進行切入,哪些鏈接點會獲得通知。顯然,切點必定是鏈接點。app

切面(Aspect)是通知和切點的結合。通知和切點共同定義了切面的所有內容——是什麼,什麼時候,何地完成功能。spring-boot

引入(Introduction)容許咱們向現有的類中添加新方法或者屬性。性能

織入(Weaving)是把切面應用到目標對象並建立新的代理對象的過程,分爲編譯期織入、類加載期織入和運行期織入。測試

3、Spring Boot AOP實戰

3.1 引入依賴

Spring Boot使用AOP須要添加spring-boot-starter-aop依賴,以下:代理

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

不須要再添加aspectjweaver的依賴了,由於spring-boot-starter-aop包含了aspectjweaver,而且版本是較新的版本,若是在添加老版本(如1.5.4)啓動會報錯。
Maven依賴日誌

3.2 編寫用於攔截的bean

直接定義一個controller,代碼以下:code

@RestController
public class AopController {

    @RequestMapping("/hello")
    public String sayHello(){
        System.out.println("hello");
        return "hello";
    }
}

3.3 定義切面

Spring採用@AspectJ註解對POJO進行標註,該註解代表該類不只僅是一個POJO,仍是一個切面。切面是切點和通知的結合,那麼定義一個切面就須要編寫切點和通知。在代碼中,只須要添加@Aspect註解便可。

3.3.1 定義切點

切點是經過@Pointcut註解和切點表達式定義的。

@Pointcut註解能夠在一個切面內定義可重用的切點。

因爲Spring切面粒度最小是達到方法級別,而execution表達式能夠用於明確指定方法返回類型,類名,方法名和參數名等與方法相關的部件,而且實際中,大部分須要使用AOP的業務場景也只須要達到方法級別便可,於是execution表達式的使用是最爲普遍的。如圖是execution表達式的語法:

execution表示在方法執行的時候觸發。以「」開頭,代表方法返回值類型爲任意類型。而後是全限定的類名和方法名,「」能夠表示任意類和任意方法。對於方法參數列表,可使用「..」表示參數爲任意類型。若是須要多個表達式,可使用「&&」、「||」和「!」完成與、或、非的操做。

切點表達式

3.3.2 定義通知

通知有五種類型,分別是:

前置通知(@Before):在目標方法調用以前調用通知

後置通知(@After):在目標方法完成以後調用通知

環繞通知(@Around):在被通知的方法調用以前和調用以後執行自定義的方法

返回通知(@AfterReturning):在目標方法成功執行以後調用通知

異常通知(@AfterThrowing):在目標方法拋出異常以後調用通知

代碼中定義了三種類型的通知,使用@Before註解標識前置通知,打印「beforeAdvice...」,使用@After註解標識後置通知,打印「AfterAdvice...」,使用@Around註解標識環繞通知,在方法執行前和執行以後分別打印「before」和「after」。這樣一個切面就定義好了,代碼以下:

@Aspect
@Component
public class AopAdvice {

    @Pointcut("execution (* com.shangguan.aop.controller.*.*(..))")
    public void test() {

    }

    @Before("test()")
    public void beforeAdvice() {
        System.out.println("beforeAdvice...");
    }

    @After("test()")
    public void afterAdvice() {
        System.out.println("afterAdvice...");
    }

    @Around("test()")
    public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
        System.out.println("before");
        try {
            proceedingJoinPoint.proceed();
        } catch (Throwable t) {
            t.printStackTrace();
        }
        System.out.println("after");
    }

}

3.4 啓動測試

完成以後的代碼結構如圖所示:

代碼結構

運行AopApplication,在瀏覽器訪問http://localhost:8080/hello,不出意外,控制檯輸出如圖所示:

控制檯輸出結果

相關文章
相關標籤/搜索