日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
漲知識!Spring AOP還能這么玩,看看你的項目能否用上

環(huán)境:Spring5.3.23

本篇文章將介紹兩個主題:

  • 控制流切入點(動態(tài)切入點)
  • 引介通知

1. 簡介

Spring AOP是Spring框架的一個重要組成部分,它允許開發(fā)者定義跨多個模塊的橫切關(guān)注點,例如日志記錄、事務(wù)管理、安全等??刂屏髑腥牒鸵橥ㄖ荢pring AOP中的兩個關(guān)鍵特性,它們能夠增強程序的可維護性和可讀性。本文將深入探討這兩個特性的工作原理和使用方法。

控制流切入

控制流切入允許我們根據(jù)方法調(diào)用的控制流來定義切入點??刂屏髑腥朦c與當前調(diào)用堆棧匹配。例如,如果連接點被com.pack.service包中的方法或PersonService類調(diào)用,它可能會觸發(fā)??刂屏髑腥朦c是通過使用org.springframework.aop.support.ControlFlowPointcut類指定的。

引介通知

引介通知能夠聲明被建議的對象實現(xiàn)給定的接口,并代表這些對象提供該接口的實現(xiàn)。簡單說:你有個PersonService類,引介通知能夠讓你不修改代碼的情況下去實現(xiàn)你給定的任意接口(CommonDAO)。

2. 實戰(zhàn)案例

2.1 控制流切入點

準備基礎(chǔ)類

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

定義切面類Advisor

低級切面Advisor,平時使用的@Aspect算是高級切面類,而這些高級切面類最終會被轉(zhuǎn)換為Advisor低級切面類。

@Component
public class PackControlFlowAdvisor extends DefaultPointcutAdvisor {
  private static MethodInterceptor logInterceptor = invocation -> {
    System.out.println("before log...") ;
    Object ret = invocation.proceed() ;
    System.out.println("after log...") ;
    return ret ;
  } ;
  // 要進行匹配的類
  private static Class clazz = PersonService.class ;
  // 要進行匹配的方法(可以為null,這樣指定類中的所有方法都會被匹配攔截)
  private static String methodName = "save" ;
  private static ControlFlowPointcut pointcut = new ControlFlowPointcut(clazz, methodName) ;
  public PackControlFlowAdvisor() {
    super(pointcut, logInterceptor) ;
  }
}

測試

PersonService ps = context.getBean(PersonService.class) ;
ps.save("王五") ;

控制臺輸出

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

PersonDAO中的save方法被攔截了。什么意思?怎么PersonDAO就被攔截了,先來看上面切點的定義ControlFlowPointcut

public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher {
  public boolean matches(Class clazz) {
    return true;
  }
  public boolean matches(Method method, Class targetClass) {
    return true;
  }
  public boolean isRuntime() {
    return true;
  }
  public boolean matches(Method method, Class targetClass, Object... args) {
    // 取得當前線程的整個執(zhí)行棧(方法的調(diào)用)
    for (StackTraceElement element : new Throwable().getStackTrace()) {
      if (element.getClassName().equals(this.clazz.getName()) &&
          (this.methodName == null || element.getMethodName().equals(this.methodName))) {
        return true;
      }
    }
    return false;
  }
}

通過在這個切點類能知道:

  1. 當前容器中的所有類都會被代理;因為這里的類匹配直接返回true,2個參數(shù)的matches直接返回true,最后isRuntime返回true,最終執(zhí)行3個參數(shù)的matches方法。
  2. 每個類中方法的調(diào)用都會獲取當前執(zhí)行的棧,都會進行判斷類及方法是否被匹配。

結(jié)合上面的測試輸出結(jié)果,PersonDAO#save方法被攔截了,因為它符合匹配條件,在PersonService#save方法中調(diào)用了PersonDAO#save方法,那PersonDAO#save方法執(zhí)行棧中就包含了PersonService#save正好匹配了我們定義的切點。

簡單說:某個類中的某個方法調(diào)用時會判斷當前整個執(zhí)行棧中是否有設(shè)定好的類及方法,如果有則攔截當前的方法(執(zhí)行通知)。

注意:控制流切入點比正常切入點慢10-15倍,但在某些情況下它們是有用的。所以大家還是慎重使用吧,畢竟所有的類都被代理了(當然這里我們可以自定義matches來控制)。

2.2 引介通知

引介通知相對比較簡單直接可以在@Aspect切面類中定義

注備基礎(chǔ)類

// 這個接口是我們準備讓其它類實現(xiàn)的
public interface CommonManager {
  void calc(int a, int b) ;
}
// 默認實現(xiàn)
public class DefaultCommonManager implements CommonManager {
  @Override
  public void calc(int a, int b) {
    System.out.printf("計算a + b = %d%n", (a + b)) ;
  }
}
// 該類是我們將要通過引介增強讓其實現(xiàn)CommonManager類
@Component("us")
public class UserService {
  public void save() {
    System.out.println("UserService save...") ;
  }
}

切面類

@Aspect
public static class CommonAspect {
  /**
   * 這樣聲明后,匹配的類就會自動的實現(xiàn)這里指定的CommonManager接口,默認的實現(xiàn)類是使用DefaultCommonManager
   * value:該值決定了哪些類會被增強(實現(xiàn)指定的CommonManager接口)
   */
  @DeclareParents(value = "com.pack.main.aop_introductionadviser.IntructionDeclareMain2.*+", defaultImpl = DefaultCommonManager.class)
  public static CommonManager mixin;
}

注意:在這個切面類中我們并沒有定義@Before,@Around等同志。

測試

CommonManager c = (CommonManager) context.getBean("us") ;
c.calc(10, 20) ;

控制臺輸出

計算a + b = 30

UserService能正確的轉(zhuǎn)換為CommonManager類,這說明UserService生成的代理類實現(xiàn)了CommonManager接口類,同時在執(zhí)行方法調(diào)用的時候使用的是我們制定的默認實現(xiàn)類DefaultCommonManager。

總結(jié):控制流切入點(ControlFlowPointcut)和引介通知(@DeclareParents)是Spring AOP的兩個重要概念??刂屏髑腥朦c用于在特定的控制流條件下切入代碼,而引介通知則讓目標類具有更加強大的能力。


分享名稱:漲知識!Spring AOP還能這么玩,看看你的項目能否用上
轉(zhuǎn)載來源:http://www.5511xx.com/article/dhgppcs.html