Spring AOP 編程入門

什麼是OOP?

 面向對象編程,也稱爲OOP(即Object Oriented Programming),通過的是繼承、封裝和多態等概念來建立一種對象層次結構,用於模擬公共行爲的一個集合,最大的優點在於能夠將業務模塊進行封裝,從而達到功能複用的目的。

什麼是AOP?

  面向切面編程,也稱爲AOP(即Aspect Oriented Programming),指的是將一定的切面邏輯按照一定的方式編織到指定的業務模塊中,從而將這些業務模塊的調用包裹起來。OOP從縱向上區分出一個個的類來,而AOP則從橫向上向對象中加入特定的代碼。AOP採用"橫切"的技術,解剖開封裝的對象內部,將影響了多個類的公共行爲封裝到一個可重用模塊。將那些與業務無關,卻爲業務模塊所共同調用的邏輯或責任封裝起來,便於減少系統的重複代碼,降低模塊之間的耦合度,並有利於未來的可操作性和可維護性。

AOP相關術語 

1.切面(Aspect)

指定了當前切面邏輯所要包裹的業務模塊的範圍大小,定義了切面的全部內容——它是什麼,在何時和何處完成其功能。

2.通知(Advice)

通知定義了切面是什麼以及何時使用。除了描述切面要完成的工作,通知還解決了何時執行這個工作的問題。

  • @Before:該註解標註的方法在業務模塊代碼執行之前執行,其不能阻止業務模塊的執行,除非拋出異常;
  • @AfterReturning:該註解標註的方法在業務模塊代碼執行之後執行;
  • @AfterThrowing:該註解標註的方法在業務模塊拋出指定異常後執行;
  • @After:該註解標註的方法在所有的Advice執行完成後執行,無論業務模塊是否拋出異常;
  • @Around:該註解功能最爲強大,其所標註的方法用於編寫包裹業務模塊執行的代碼,其可以傳入一個ProceedingJoinPoint用於調用業務模塊的代碼,無論是調用前邏輯還是調用後邏輯,都可以在該方法中編寫,甚至其可以根據一定的條件而阻斷業務模塊的調用;
  • @DeclareParents:其是一種Introduction類型的模型,在屬性聲明上使用,主要用於爲指定的業務模塊添加新的接口和相應的實現。

3.連接點(Joint point)

是指在程序執行期間的一個點,比如某個方法的執行或者是某個異常的處理。在Spring AOP中,一個連接點往往代表的是一個方法執行

4.切入點(Pointcut)

是指匹配連接點的一個斷言。通知是和一個切入點表達式關聯的,並且在任何被切入點匹配的連接點上運行(舉例,使用特定的名字執行某個方法)。AOP的核心就是切入點表達式匹配連接點的思想。

切點表達式

  1. execution:Spring切面粒度最小是達到方法級別,而execution表達式可以用於明確指定方法返回類型,類名,方法名和參數名等與方法相關的,execution表達式的語法:
  •  
    execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)

 

  • modifiers-pattern:方法的可見性,如public,protected;
  • ret-type-pattern:方法的返回值類型,如int,void等;
  • declaring-type-pattern:方法所在類的全路徑名,如com.example.demo.controller;
  • name-pattern:方法名類型,如EatWMZ();
  • param-pattern:方法的參數類型,如java.lang.String;
  • throws-pattern:方法拋出的異常類型,如java.lang.Exception;

如:

execution(public * com.example.demo.controller.AopController.*(..)))

   2.within:within表達式的粒度爲類,其參數爲全路徑的類名(可使用通配符),表示匹配當前表達式的所有類都將被當前方法環繞。

如:

within( com.example.demo.controller.AopController)

 表示匹配com.example.demo.controller.AopController 下的所有方法


 

 

5.引入(Introduction)

代表了對一個類型額外的方法或者屬性的聲明。Spring AOP允許引入新接口到任何被通知對象(以及一個對應實現)。比如,可以使用一個引入去使一個bean實現IsModified接口,從而簡化緩存機制。(在AspectJ社區中,一個引入也稱爲一個inter-type declaration類型間聲明)

6.目標對象(Target object)

是指被一個或多個切面通知的那個對象。也指被通知對象("advised object"),由於Spring AOP是通過運行時代理事項的,這個目標對象往往是一個代理對象

7.AOP 代理(AOP proxy)

是指通過AOP框架創建的對象,用來實現切面合約的(執行通知方法等等)。在Spring框架中,一個AOP代理是一個JDK動態代理或者是一個CGLIB代理

8.織入(Weaving)

將切面和其他應用類型或者對象連接起來,創建一個被通知對象。這些可以在編譯時(如使用AspectJ編譯器)、加載時或者運行時完成。Spring AOP,比如其他純Java AOP框架一般是在運行時完成織入。

SpringBoot中集成AOP

1.pom.xml引入

maven依賴添加如下
<!--引入SpringBoot的Web模塊-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
 
<!--引入AOP依賴-->
   <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.5</version>
   </dependency>

 2.定義切面類

@Aspect 註解 使之成爲切面類

@Component 註解 把切面類加入到IOC容器中

package com.example.demo.aop;

import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * 餓鳥嘛配送
 **/
@Aspect
@Component
public class EatAop {

    /**
    *@description 定義切入點,切入點爲com.example.demo.controller.AopController中的所有函數
    *@description 通過@Pointcut註解聲明頻繁使用的切點表達式
    * */
    @Pointcut("execution(public * com.example.demo.controller.AopController.*(..)))")
    public void EatAop()
    {

    }
    /**
     * @description  在連接點執行之前執行的通知
     */
    @Before("EatAop()")
    public void doBeforeEat(){
        System.out.println("餓鳥嘛配送員登錄接單系統爲接單做準備!");
    }

    /**
     * @description  在連接點執行之後執行的通知(返回通知和異常通知的異常)
     */
    @After("EatAop()")
    public void doAfterEat(){
        System.out.println("餓鳥嘛配送員爲今天的外賣單量感到異常喫驚!");
    }

    /**
     * @description  在連接點執行之後執行的通知(返回通知)
     */
    @AfterReturning("EatAop()")
    public void doAfterReturningEat(){
        System.out.println("返回的通知:餓鳥嘛配送員接單完畢,並會心一笑百媚生!");
    }

    /**
     * @description  在連接點執行之後執行的通知(異常通知)
     */
    @AfterThrowing("EatAop()")
    public void doAfterThrowingGame(){
        System.out.println("異常通知:服務錯誤,請聯繫餓鳥嘛系統管理員!");
    }

}

3.新建AopController

package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class AopController {

    @RequestMapping(value = "/EatWMZ")
    public void EatWMZ(){
        System.out.println("王麻子點了一份瓜皮香鍋");
    }
    @RequestMapping(value = "/EatZS")
    public void EatZS(){
        System.out.println("張三點了一份爆漿牛丸");
    }
}

 

訪問http://127.0.0.1:8080/api/EatWMZ

 

小結

   本文首先對AOP進行了簡單介紹,然後介紹了切面中的相關術語,舉例說明切點表達式其中常用的兩種,最後做了簡單的demo旨在說明切面邏輯(advice)下各個類型執行的順序。

源碼:https://github.com/LeeCurtain/demo.git

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