自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

你了解Spring AOP的這個(gè)技能點(diǎn)嗎?有什么應(yīng)用場(chǎng)景?

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

環(huán)境:Spring5.3.23

1. 介紹

今天看Spring文檔看到這么一個(gè)知識(shí)點(diǎn)《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控制流切入點(diǎn)在概念上類似于aspectj cflow切入點(diǎn),盡管功能不那么強(qiáng)大。(目前還沒(méi)有辦法指定一個(gè)切入點(diǎn)在與另一個(gè)切入點(diǎn)匹配的連接點(diǎn)下面運(yùn)行。)控制流切入點(diǎn)與當(dāng)前調(diào)用堆棧匹配。例如,如果連接點(diǎn)由com.mycompany.web包中的方法或someecaller類調(diào)用,則可能會(huì)觸發(fā)該連接點(diǎn)??刂屏髑腥朦c(diǎn)是通過(guò)使用org.springframework.aop.support.ControlFlowPointcut類指定的。

其實(shí)看完這個(gè),可能你還是不懂什么意思,接下來(lái)我們來(lái)跑一個(gè)實(shí)例,就能明白撒意思了。

2. Control Flow實(shí)例

準(zhǔn)備幾個(gè)方法嵌套調(diào)用的類

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) ;
  }
}

上面的類及方法調(diào)用非常簡(jiǎn)單:PersonManager ---> PersonService ---> PersonDAO。接下來(lái)是通過(guò)編程的方式創(chuàng)建PersonService代理對(duì)象。

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


PersonManager pm = new PersonManager() ;


Class<?> clazz = PersonManager.class ;
String methodName = "index" ;
// 定義切入點(diǎn)
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) ;
// 通過(guò)ProxyFactory創(chuàng)建代理對(duì)象,創(chuàng)建的是PersonService對(duì)象的代理
ProxyFactory factory = new ProxyFactory(target) ;
factory.addAdvisor(advisor) ;
// 基于CGLIB生成代理
factory.setProxyTargetClass(true) ;
PersonService ps = (PersonService) factory.getProxy() ;


pm.setPs(ps) ;


pm.index("張三") ;

控制臺(tái)輸出

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

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

ControlFlowPointcut核心方法

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

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

有了上面源碼的分析后,我們?cè)賮?lái)看看上面的示例代碼:

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

分析到這你應(yīng)該知道這個(gè)Control Flow有撒用了吧,總結(jié):

Control Flow就是用來(lái)判斷當(dāng)前執(zhí)行的線程棧中(所有方法的調(diào)用)是否與你給定的類及方法匹配,只有匹配了才能執(zhí)行我們的增強(qiáng)(通知)代碼。

簡(jiǎn)單說(shuō):我PersonService想監(jiān)控PersonManager中的index方法是否調(diào)用了我。

官方有這段說(shuō)明:

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.

大意:與靜態(tài)快捷方式相比,動(dòng)態(tài)快捷方式的評(píng)估成本更高。它們會(huì)考慮方法參數(shù)和靜態(tài)信息。這意味著每次調(diào)用方法時(shí)都必須對(duì)其進(jìn)行評(píng)估,而且由于參數(shù)會(huì)發(fā)生變化,因此無(wú)法緩存評(píng)估結(jié)果??刂屏骺旖莘绞骄褪且粋€(gè)主要的例子。

3. Control Flow性能

同樣來(lái)自官方說(shuō)明:

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.

大意:與其他動(dòng)態(tài)切入點(diǎn)相比,控制流切入點(diǎn)在運(yùn)行時(shí)評(píng)估的成本要高得多。在Java1.4中,成本大約是其他動(dòng)態(tài)切入點(diǎn)的五倍。

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

責(zé)任編輯:武曉燕 來(lái)源: Spring全家桶實(shí)戰(zhàn)案例源碼
相關(guān)推薦

2020-12-21 14:42:42

大數(shù)據(jù)云計(jì)算人工智能

2022-12-08 10:40:06

聲明式事務(wù)AOP

2022-07-24 21:56:38

元宇宙

2021-02-20 10:31:54

人工智能人工智能應(yīng)用

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應(yīng)用場(chǎng)景

2019-08-12 16:22:07

Python線程場(chǎng)景

2021-07-05 16:53:04

AI人工智能教育

2012-10-23 09:32:07

2023-10-29 08:35:47

AndroidAOP編程

2023-11-28 08:20:25

2020-11-20 10:53:46

邊緣計(jì)算

2022-10-17 00:27:20

二叉樹(shù)數(shù)組索引

2017-07-27 09:53:34

spring AopspringCIO

2014-09-25 12:08:12

微信企業(yè)號(hào)功能特點(diǎn)

2011-05-17 15:24:18

Shibboleth認(rèn)證

2012-09-27 10:24:22

監(jiān)控機(jī)房
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)