歡迎您光臨本站 註冊首頁

Spring AOP註解案例及基本原理詳解

←手機掃碼閱讀     e36605 @ 2020-06-29 , reply:0

切面:Aspect
 

切面=切入點+通知。在老的spring版本中通常用xml配置,現在通常是一個類帶上@Aspect註解。切面負責將 橫切邏輯(通知) 編織 到指定的連接點中。

目標對象:Target
 

將要被增強的對象。

連接點:JoinPoint
 

可以被攔截到的程序執行點,在spring中就是類中的方法。

切入點:PointCut
 

需要執行攔截的方法,也就是具體實施了橫切邏輯的方法。切入點的規則在spring中通過AspectJ pointcut expression language來描述。
 

切入點與連接點的區別:連接點是所有可以被"切"的點;切入點是真正要切的點。

通知:Advice
 

針對切入點的橫切邏輯,包含“around”、“before”和“after”等不同類型的通知。
 

通知的作用點如其命名:

  • before:在切入點之前執行

  • after:在切入點之後執行

  • around:在切入點攔截方法,自定義前後,更靈活

還有一些異常處理的通知,這裡不一一舉例
 

織入:Weaving
 

將切面和目標對象連接起來,創建代理對象的過程。spring中用的是動態代理。假如目標對象有接口,使用jdk動態代理;否則使用cglib動態代理。

說了這麼多概念,看看代碼實現可能會使讀者理解的更深刻一些,這裡簡單寫一個通過註解增強方法的AOP-Demo。
 首先是切面類:

  package com.example.demo.aop;    import org.aspectj.lang.JoinPoint;  import org.aspectj.lang.ProceedingJoinPoint;  import org.aspectj.lang.annotation.*;  import org.springframework.stereotype.Component;    /**   * @author Fcb   * @date 2020/6/20   * @description 切面類=切入點+通知   */  @Aspect  @Component  public class LogAspect {      //這個方法定義了切入點    @Pointcut("@annotation(com.example.demo.aop.anno.MyLog)")    public void pointCut() {}      //這個方法定義了具體的通知    @After("pointCut()")    public void recordRequestParam(JoinPoint joinPoint) {      for (Object s : joinPoint.getArgs()) {        //打印所有參數,實際中就是記錄日誌了        System.out.println("after advice : " + s);      }    }      //這個方法定義了具體的通知    @Before("pointCut()")    public void startRecord(JoinPoint joinPoint) {      for (Object s : joinPoint.getArgs()) {        //打印所有參數        System.out.println("before advice : " + s);      }    }      //這個方法定義了具體的通知    @Around("pointCut()")    public Object aroundRecord(ProceedingJoinPoint pjp) throws Throwable {      for (Object s : pjp.getArgs()) {        //打印所有參數        System.out.println("around advice : " + s);      }      return pjp.proceed();    }  }

 

註解:

  package com.example.demo.aop.anno;  import java.lang.annotation.*;  /**   * @author Fcb   * @date 2020/6/20   * @description   */  @Documented  @Retention(RetentionPolicy.RUNTIME)  @Target({ElementType.METHOD, ElementType.TYPE})  public @interface MyLog {  }

 

目標類:

  package com.example.demo.aop.target;    import com.example.demo.aop.anno.MyLog;  import org.springframework.web.bind.annotation.RequestMapping;  import org.springframework.web.bind.annotation.RequestParam;  import org.springframework.web.bind.annotation.RestController;    /**   * @author Fcb   * @date 2020/6/20   * @description   */  @RestController  public class MockController {      @RequestMapping("/hello")    @MyLog    public String helloAop(@RequestParam String key) {      System.out.println("do something...");      return "hello world";    }    }

 

最後是測試類:

  package com.example.demo.aop.target;    import org.junit.jupiter.api.Test;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.boot.test.context.SpringBootTest;  /**   * @author Fcb   * @date 2020/6/20   * @description   */  @SpringBootTest  class MockControllerTest {    @Autowired    MockController mockController;      @Test    void helloAop() {      mockController.helloAop("aop");    }  }

 

控制檯結果:

around advice : aop
 before advice : aop
 do something...
 after advice : aop

                                                       

   


[e36605 ] Spring AOP註解案例及基本原理詳解已經有210次圍觀

http://coctec.com/docs/java/show-post-240279.html