成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

你了解Spring AOP的這個技能點嗎?有什么應用場景?

開發 前端
從輸出的結果發現,在PersonService#save方法之前之前和之后分別打印了日志信息。原理是什么呢?這里我們需要先看ControlFlowPointcut 切入點是如何工作的。

環境:Spring5.3.23

1. 介紹

今天看Spring文檔看到這么一個知識點《Control Flow Pointcuts》都不好翻譯

官方原文:

Spring control flow pointcuts are conceptually similar to AspectJ cflow pointcuts, although less powerful. (There is currently no way to specify that a pointcut runs below a join point matched by another pointcut.) A control flow pointcut matches the current call stack. For example, it might fire if the join point was invoked by a method in the com.mycompany.web package or by the SomeCaller class. Control flow pointcuts are specified by using the org.springframework.aop.support.ControlFlowPointcut class.

大意:Spring控制流切入點在概念上類似于aspectj cflow切入點,盡管功能不那么強大。(目前還沒有辦法指定一個切入點在與另一個切入點匹配的連接點下面運行。)控制流切入點與當前調用堆棧匹配。例如,如果連接點由com.mycompany.web包中的方法或someecaller類調用,則可能會觸發該連接點。控制流切入點是通過使用org.springframework.aop.support.ControlFlowPointcut類指定的。

其實看完這個,可能你還是不懂什么意思,接下來我們來跑一個實例,就能明白撒意思了。

2. Control Flow實例

準備幾個方法嵌套調用的類

static class PersonDAO {
  public void save(String name) {
    System.out.println("PersonDAO save method invoke...") ;
  }
}
static class PersonService {
  private PersonDAO dao ;
  public PersonService(PersonDAO dao) {
    this.dao = dao ;
  }
  public void save(String name) {
    System.out.println("PersonService save method inovke...") ;
    this.dao.save(name) ;
  }
}


static class PersonManager {
  private PersonService ps ;
  public void setPs(PersonService ps) {
    this.ps = ps ;
  }
  public void index(String name) {
    System.out.println("PersonManager index method invoke...") ;
    this.ps.save(name) ;
  }
}

上面的類及方法調用非常簡單:PersonManager ---> PersonService ---> PersonDAO。接下來是通過編程的方式創建PersonService代理對象。

// 實例化上面的類
PersonDAO dao = new PersonDAO() ;
PersonService target = new PersonService(dao) ;


PersonManager pm = new PersonManager() ;


Class<?> clazz = PersonManager.class ;
String methodName = "index" ;
// 定義切入點
ControlFlowPointcut pointcut = new ControlFlowPointcut(clazz, methodName) ;
// 定義通知
MethodInterceptor logInterceptor = invocation -> {
  System.out.println("before log...") ;
  Object ret = invocation.proceed() ;
  System.out.println("after log...") ;
  return ret ;
} ;
// 定義切面


DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, logInterceptor) ;
// 通過ProxyFactory創建代理對象,創建的是PersonService對象的代理
ProxyFactory factory = new ProxyFactory(target) ;
factory.addAdvisor(advisor) ;
// 基于CGLIB生成代理
factory.setProxyTargetClass(true) ;
PersonService ps = (PersonService) factory.getProxy() ;


pm.setPs(ps) ;


pm.index("張三") ;

控制臺輸出

PersonManager index method invoke...
before log...
PersonService save method inovke...
PersonDAO save method invoke...
after log...

從輸出的結果發現,在PersonService#save方法之前之前和之后分別打印了日志信息。原理是什么呢?這里我們需要先看ControlFlowPointcut 切入點是如何工作的。

ControlFlowPointcut核心方法

這里只列出了幾個重要的方法,在spring中只支持方法級別的攔截。

public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher, Serializable {
  private final Class<?> clazz;
  @Nullable
  private final String methodName;
  // 對應類級別的匹配全部返回true,就是都匹配
  @Override
  public boolean matches(Class<?> clazz) {
    return true;
  }
  // 方法匹配,直接true
  @Override
  public boolean matches(Method method, Class<?> targetClass) {
    return true;
  }
  // 這里是關鍵,只有isRuntime返回了true才有可能調用下面3個參數的matches方法
  @Override
  public boolean isRuntime() {
    return true;
  }
  // 該方法的調用需要上面2個參數的matches方法返回true且isRuntime方法也返回true才會調用這里
  @Override
  public boolean matches(Method method, Class<?> targetClass, Object... args) {
    // 遍歷當前線程的執行棧情況(也就是當前方法的調用棧情況)
    for (StackTraceElement element : new Throwable().getStackTrace()) {
      // 這里就開始判斷當前執行的類是否與給定的類相同 && 當前設置的methodName為空或者當前棧執行的方法名與給定的方法名相同
      if (element.getClassName().equals(this.clazz.getName()) &&
          (this.methodName == null || element.getMethodName().equals(this.methodName))) {
        // 最終這里只有返回了true,我們上面的通知MethodInterceptor才會被執行
        return true;
      }
    }
    return false;
  }
}

有了上面源碼的分析后,我們再來看看上面的示例代碼:

// 指明要匹配的類
Class<?> clazz = PersonManager.class ;
// 指明要匹配的方法名
String methodName = "index" ;
/** 
 * 將傳入到切入點中;而在該切入點的matches方法中進行了判斷,
 * 整個執行的線程棧中的所有類及方法是否與這里給定的相同,
 * 只有相同了攔截器才能執行
 */
ControlFlowPointcut pointcut = new ControlFlowPointcut(clazz, methodName) ;

分析到這你應該知道這個Control Flow有撒用了吧,總結:

Control Flow就是用來判斷當前執行的線程棧中(所有方法的調用)是否與你給定的類及方法匹配,只有匹配了才能執行我們的增強(通知)代碼。

簡單說:我PersonService想監控PersonManager中的index方法是否調用了我。

官方有這段說明:

Dynamic pointcuts are costlier to evaluate than static pointcuts. They take into account method arguments as well as static information. This means that they must be evaluated with every method invocation and that the result cannot be cached, as arguments will vary.

The main example is the control flow pointcut.

大意:與靜態快捷方式相比,動態快捷方式的評估成本更高。它們會考慮方法參數和靜態信息。這意味著每次調用方法時都必須對其進行評估,而且由于參數會發生變化,因此無法緩存評估結果。控制流快捷方式就是一個主要的例子。

3. Control Flow性能

同樣來自官方說明:

Control flow pointcuts are significantly more expensive to evaluate at runtime than even other dynamic pointcuts. In Java 1.4, the cost is about five times that of other dynamic pointcuts.

大意:與其他動態切入點相比,控制流切入點在運行時評估的成本要高得多。在Java1.4中,成本大約是其他動態切入點的五倍。

知道了Control Flow怎么一回事,那它有什么使用場景嗎?有使用過的還望能分享下圖片,歡迎大家留言討論。圖片

責任編輯:武曉燕 來源: Spring全家桶實戰案例源碼
相關推薦

2020-12-21 14:42:42

大數據云計算人工智能

2022-12-08 10:40:06

聲明式事務AOP

2021-02-20 10:31:54

人工智能人工智能應用

2022-07-24 21:56:38

元宇宙

2021-03-16 06:47:47

Python

2025-01-15 07:54:02

2024-01-25 10:14:09

HashSetHashMapJava

2023-07-05 08:05:17

Goerror應用場景

2022-01-05 16:16:02

查詢編程工程師

2021-07-05 16:53:04

AI人工智能教育

2019-08-12 16:22:07

Python線程場景

2023-10-29 08:35:47

AndroidAOP編程

2012-10-23 09:32:07

2020-11-20 10:53:46

邊緣計算

2023-11-28 08:20:25

2012-09-27 10:24:22

監控機房

2011-05-17 15:24:18

Shibboleth認證

2023-01-30 11:27:57

人工智能高性能計算CPU

2017-07-27 09:53:34

spring AopspringCIO

2022-10-17 00:27:20

二叉樹數組索引
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩和的一区二区 | 一级无毛片 | av在线免费网 | 国产www在线 | 99九色| 亚洲成人自拍 | 综合久| 人人人人人爽 | 亚洲精品一区久久久久久 | 免费一区在线 | 免费激情av | 国产精品久久久久久久久免费高清 | 国产大毛片| 九九久久久 | 国产精品乱码一区二区三区 | 久久aⅴ乱码一区二区三区 91综合网 | 隔壁老王国产在线精品 | 久久不卡 | 国产成人午夜电影网 | 亚洲午夜精品 | www狠狠干 | 中文字幕亚洲视频 | 成人精品一区二区三区 | 一区二区视频在线观看 | 国产精品揄拍一区二区 | 欧美bondage紧缚视频 | 九九久久精品 | 国产美女在线看 | 中文字幕一区二区三区四区 | 男人天堂网址 | 久久91精品久久久久久9鸭 | 免费人成激情视频在线观看冫 | 成人激情视频在线播放 | 日本免费在线 | 高清国产午夜精品久久久久久 | 成人不卡视频 | 日本精品一区二区 | 久久精品一级 | 不卡一区二区在线观看 | 免费一级片 | 成年人视频在线免费观看 |