天天看點

Spring Aop源碼學習--PointCut切入點

PointCut切入點簡單來說就是用來指明Advice(增強)所作用的地方(一般指方法),PointCut簡單來說是一個基于表達式的攔截條件。

PointCut接口及實作類:

Spring Aop源碼學習--PointCut切入點

PointCut接口提供了兩個接口分别對類和方法進行比對過濾,如果類及方法比對成功則Advice就可以作用在方法上。

public interface Pointcut {

  /**
   * Return the ClassFilter for this pointcut.
   * @return the ClassFilter (never {@code null})
   */
  //通過pointcut表達式對類進行過濾
  ClassFilter getClassFilter();

  /**
   * Return the MethodMatcher for this pointcut.
   * @return the MethodMatcher (never {@code null})
   */
  //通過pointcut表達式對方法進行過濾
  MethodMatcher getMethodMatcher();


  /**
   * Canonical Pointcut instance that always matches.
   */
  //比對所有的類及方法,預設傳回true
  Pointcut TRUE = TruePointcut.INSTANCE;

}      

在PointCut的子類AspectJExpressionPointcut中提供了兩個方法對類和方法進行比對判斷,其最後的過濾的處理操作還是在aspectjweaver(aspectJ類庫,AspectJ是一個專門用來實作動态代理(AOP程式設計)的類庫,AspectJ是面向切面程式設計的架構,Spring使用就是這個類庫實作動态代理的)這個jar中完成的。

//對類進行過濾比對
  @Override
  public boolean matches(Class<?> targetClass) {
    checkReadyToMatch();
    try {
      try {
        return this.pointcutExpression.couldMatchJoinPointsInType(targetClass);
      }
      catch (ReflectionWorldException ex) {
        logger.debug("PointcutExpression matching rejected target class - trying fallback expression", ex);
        PointcutExpression fallbackExpression = getFallbackPointcutExpression(targetClass);
        if (fallbackExpression != null) {
          return fallbackExpression.couldMatchJoinPointsInType(targetClass);
        }
      }
    }
    catch (Throwable ex) {
      logger.debug("PointcutExpression matching rejected target class", ex);
    }
    return false;
  }

  //對方法進行過濾比對
  @Override
  public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) {
    checkReadyToMatch();
    Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
    ShadowMatch shadowMatch = getShadowMatch(targetMethod, method);
    if (shadowMatch.alwaysMatches()) {
      return true;
    }
    else if (shadowMatch.neverMatches()) {
      return false;
    }
    else {
      if (beanHasIntroductions) {
        return true;
      }
      RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
      return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));
    }
  }      

總結:PointCut接口及其實作類就是根據我們配置的類及方法的過濾規則在調用Advice之前進行過濾,看看是否需要調用Advice。