为什么 Spring Framework 中的 MethodMatcher 接口将 targetClass 作为参数,其中 Pointcut 已经定义了一个 Classfilter?

Why does the MethodMatcher interface in Spring Framework takes a targetClass as argument, where Pointcut already defines a Classfilter?

Pointcut interface in Spring Framework 包含 2 个方法:

public interface Pointcut {

    /**
     * Return the ClassFilter for this pointcut.
     * @return the ClassFilter (never {@code null})
     */
    ClassFilter getClassFilter();

    /**
     * Return the MethodMatcher for this pointcut.
     * @return the MethodMatcher (never {@code null})
     */
    MethodMatcher getMethodMatcher();


    /**
     * Canonical Pointcut instance that always matches.
     */
    Pointcut TRUE = TruePointcut.INSTANCE;

}

ClassFilter接口已经声明,它的唯一目的是决定class是否可以通过过滤器:

/**
 * Filter that restricts matching of a pointcut or introduction to
 * a given set of target classes.
 *
 * <p>Can be used as part of a {@link Pointcut} or for the entire
 * targeting of an {@link IntroductionAdvisor}.
 *
 * @author Rod Johnson
 * @see Pointcut
 * @see MethodMatcher
 */
public interface ClassFilter {

    /**
     * Should the pointcut apply to the given interface or target class?
     * @param clazz the candidate target class
     * @return whether the advice should apply to the given target class
     */
    boolean matches(Class<?> clazz);


    /**
     * Canonical instance of a ClassFilter that matches all classes.
     */
    ClassFilter TRUE = TrueClassFilter.INSTANCE;

}

我不明白的是,为什么 MethodMatcher 接口中的方法再次检查class资格?为什么这个接口的方法有 targetClass 参数?

public interface MethodMatcher {

    /**
     * Perform static checking whether the given method matches. If this
     * returns {@code false} or if the {@link #isRuntime()} method
     * returns {@code false}, no runtime check (i.e. no.
     * {@link #matches(java.lang.reflect.Method, Class, Object[])} call) will be made.
     * @param method the candidate method
     * @param targetClass the target class (may be {@code null}, in which case
     * the candidate class must be taken to be the method's declaring class)
     * @return whether or not this method matches statically
     */
    boolean matches(Method method, Class<?> targetClass);

    /**
     * Check whether there a runtime (dynamic) match for this method,
     * which must have matched statically.
     * <p>This method is invoked only if the 2-arg matches method returns
     * {@code true} for the given method and target class, and if the
     * {@link #isRuntime()} method returns {@code true}. Invoked
     * immediately before potential running of the advice, after any
     * advice earlier in the advice chain has run.
     * @param method the candidate method
     * @param targetClass the target class (may be {@code null}, in which case
     * the candidate class must be taken to be the method's declaring class)
     * @param args arguments to the method
     * @return whether there's a runtime match
     * @see MethodMatcher#matches(Method, Class)
     */
    boolean matches(Method method, Class<?> targetClass, Object... args);


    /**
     * Canonical instance that matches all methods.
     */
    MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;

} 

MethodMatcher.matches(Method method, Class<?> targetClass)中指定的targetClass不用于检查目标调用的资格class

它用于找到最具体的目标方法,它适用于给定方法(指定为参数)的目标class。它还解决了 Java bridge methods.

的问题

这是来自 org.springframework.aop.aspectj.AspectJExpressionPointcut class 的示例 matches 方法。

public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) {
    this.checkReadyToMatch();
    Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
    ShadowMatch shadowMatch = this.getShadowMatch(targetMethod, method);
    ...
}

这是来自 org.springframework.aop.support.AopUtils#getMostSpecificMethod

的 Javadoc

Given a method, which may come from an interface, and a target class used in the current AOP invocation, find the corresponding target method if there is one. E.g. the method may be IFoo.bar() and the target class may be DefaultFoo. In this case, the method may be DefaultFoo.bar(). This enables attributes on that method to be found.

NOTE: In contrast to org.springframework.util.ClassUtils#getMostSpecificMethod, this method resolves Java 5 bridge methods in order to retrieve attributes from the original method definition.