成人免费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

2022-01-05 16:16:02

查詢編程工程師

2023-07-05 08:05:17

Goerror應用場景

2021-07-05 16:53:04

AI人工智能教育

2019-08-12 16:22:07

Python線程場景

2012-10-23 09:32:07

2023-10-29 08:35:47

AndroidAOP編程

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

2018-02-25 22:37:21

應用開關Java

2014-09-25 12:08:12

微信企業號功能特點
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲香蕉 | 国产精品欧美大片 | 在线精品一区二区 | 日韩成人在线网站 | 超碰导航 | 欧美久操网 | 毛片a级| 中文字幕日韩欧美 | 日韩精品久久久 | 久久精品综合 | 夜夜爽99久久国产综合精品女不卡 | 精品一区二区视频 | 欧美888| 一区二区三区日 | 97精品久久 | 精品亚洲国产成av人片传媒 | 欧美片网站免费 | 在线国产一区 | 国产精品久久国产精品久久 | www.久久精品视频 | 特一级黄色毛片 | 国产91观看| 色综合久久久 | 日韩伦理一区二区 | 天天干天天插 | 网站一区二区三区 | 国产成人网 | 手机av网 | 九九亚洲精品 | 国产亚洲精品精品国产亚洲综合 | 91影院| 日本视频中文字幕 | 日韩免费电影 | 色资源站 | 一级做a | 欧美综合一区二区 | 永久网站 | a级片播放| 国产一区二 | 日韩精品一区二区三区中文在线 | 久久网一区二区 |