探秘SpringAop(一)_介紹以及使用詳解


常用的編程范式

AOP 是什么

  • 是一種編程方式,不是編程語言
  • 解決特定問題,不能解決所有的問題
  • OOP的補充,不是代替

AOP 初衷

  • DRY: Don't repeat yourself(代碼重復)
  • SoC:Separation of Concerns(關注點分離)
    • 水平分離:展示層-> 服務層 -> 持久層
    • 垂直分離:模塊划分(訂單、庫存等)
    • 切面分離:分離功能性需求與非功能性需求

AOP的優點

  • 集中處理某一關注點/橫切邏輯
  • 可以很方便地添加/刪除關注點
  • 侵入性少,增強代碼可讀性及可維護性

AOP的應用場景

  • 權限控制
  • 緩存控制
  • 性能監控
  • ...

支持AOP的語言

  • Java、Python、PHP...

SpringAOP使用詳解

首先,我整理了一張圖,讓大家更好的梳理SpringAOP的使用

@Poincut 詳解

匹配包/類型_ within()
  • 匹配ProductService類里頭的所有方法

  • @Pointcut("within(com.zhb.service.ProductService)")

  • 匹配com.zhb包及子包下所有類的方法

  • @Pointcut("within(com.zhb..*)")

匹配對象
  • 匹配AOP對象的目標對象為指定類型的方法,即LogService的aop代理對象的方法

  • @Pointcut("this(com.zhb.log.Loggable)")

  • 匹配實現Loggable接口的目標對象(而不是aop代理后的對象)的方法

  • @Pointcut("target(com.zhb.log.Loggable)")

  • this 可以攔截 DeclareParents(Introduction)

  • target 不攔截 DeclareParents(Introduction)

  • 匹配所有以Service結尾的bean里頭的方法

  • @Pointcut("bean(*Service)")

匹配參數 args()
  • 匹配任何以find開頭而且只有一個Long參數的方法

  • @Pointcut("execution(* ..find(Long))")

  • 匹配任何以find開頭的而且第一個參數為Long型的方法

  • @Pointcut("execution(* ..find(Long,..))")

  • 匹配任何只有一個Long參數的方法

  • @Pointcut("within(com.zhb..*) && args(Long)")

  • 匹配第一個參數為Long型的方法

  • @Pointcut("within(com.zhb..*) && args(Long,..)")

匹配注解
  • 匹配方法標注有AdminOnly的注解的方法
  • @Pointcut("@annotation(com.zhb.anno.AdminOnly) && within(com.zhb..*)")
  • 匹配標注有NeedSecured的類底下的方法 //class級別
  • @Pointcut("@within(com.zhb.anno.NeedSecured) && within(com.zhb..*)")
  • 匹配標注有NeedSecured的類及其子類的方法 //runtime級別
  • 在spring context的環境下,二者沒有區別
  • @Pointcut("@target(com.zhb.anno.NeedSecured) && within(com.zhb..*)")
  • 匹配傳入的參數類標注有Repository注解的方法
  • @Pointcut("@args(com.zhb.anno.NeedSecured) && within(com.zhb..*)")
匹配方法
  • 匹配任何公共方法

  • @Pointcut("execution(public * com.zhb.service..(..))")

  • 匹配com.zhb包及子包下Service類中無參方法

  • @Pointcut("execution(* com.zhb..Service.())")

  • 匹配com.zhb包及子包下Service類中的任何只有一個參數的方法

  • @Pointcut("execution(* com.zhb..Service.(*))")

  • 匹配com.zhb包及子包下任何類的任何方法

  • @Pointcut("execution(* com.zhb...(..))")

  • 匹配com.zhb包及子包下返回值為String的任何方法

  • @Pointcut("execution(String com.zhb...(..))")

  • 匹配異常

  • execution(public * com.zhb.service..(..) throws java.lang.IllegalAccessException)

其實,這么多實際工作中用到的比較少,我平時就用過execution 這一個。

Advice 詳解

  • @Before(value = "matchLongArg() && args(productId)")
  • public void beforeWithArgs(Long productId)
  • @AfterReturning(value = "matchReturn()",returning = "returnValue")
  • public void getReulst(Object returnValue)

給出一段常用代碼


    @Pointcut("within(com.zhb.controller.GirlController)")
    public void mathType(){}

    @Before(value = "mathType() && args(obj)")
    public void before(Object obj){

        System.out.println("這里是目標方法執行前先執行");
        //獲取參數
        System.out.println("這里是目標方法的參數"+obj.toString());
    }
    @AfterReturning(returning = "entity",value = "mathType()")
    public void after(JoinPoint joinPoint,Object entity){
        System.out.println("這里是目標方法執行完並成功返回結果 正常結束后才執行");
        System.out.println("方法的返回結果為"+entity);
        System.out.println("目標方法內的參數為"+ Arrays.asList(joinPoint.getArgs()));
    }
    @AfterThrowing(throwing = "e",value = "mathType()")
    public void mathThrow(Throwable  e){
        System.out.println("這里是目標方法拋出異常后才執行");
        System.out.println("異常信息為"+e);
    }

大家再用到的時候可以自行搜索


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM