Pointcut 介面


Spring是根據類別名稱與方法名稱來定義Pointcut,當呼叫的類別與方法名稱符合Pointcut的定義時,將Advice縫合至應用程式上以提供服務。

Spring的Pointcut是透過實作org.springframework.aop.Pointcut介面來實現,其定義如下:
package org.springframework.aop;

public interface Pointcut {
    ClassFilter getClassFilter();  
    MethodMatcher getMethodMatcher();
    Pointcut TRUE = TruePointcut.INSTANCE;
}

Pointcut.TRUE是Pointcut介面的簡單實作,它傳回的ClassFilter是ClassFilter.TRUE,而傳回的MethodMatcher是傳回MethodMatcher.TRUE。

ClassFilter介面決定了一個類別是否要應用Advice,其定義如下所示:
package org.springframework.aop;

public interface ClassFilter {
    boolean matches(Class clazz);
    ClassFilter TRUE = TrueClassFilter.INSTANCE;
}

matches()方法中要決定傳入的類別是不是符合Pointcut的定義,ClassFilter.TRUE是ClassFilter介面的簡單實 作,它的matches()方法總是傳回true,如果您想要建立的Pointcut只考慮到方法名稱,則可以使用這個方法。

而MethodMatcher決定了某個方法是否要應用Advice,其定義如下所示:
package org.springframework.aop;

import java.lang.reflect.Method;

public interface MethodMatcher {
    boolean matches(Method method, Class targetClass);
    boolean isRuntime();
    boolean matches(Method method,
                       Class targetClass, Object[] args);
    MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
}

matches()方法決定了某個類別的某個方法是否符合Pointcut定義,有兩個版本,第一個版本使用於靜態Pointcut,像是 NameMatchMethodPointcutAdvisor 、 RegExpMethodPointcutAdvisor,第一個方法總是會被執行,如果是靜態Pointcut,則isRuntime()會傳回 false,此時第二個matches()方法不會被執行,只有在isRuntime()為true時,第二個版本的matches()才會被執行,例如 ControlFlowPointcut 。

MethodMatcher.TRUE是MethodMatcher的簡單實作,它的第一個版本的matches()總是傳回true, isRuntime()總是傳回false,表示靜態Pointcut,所以您不可以呼叫第二個版本的matches()方法,否則就會丟出 UnsupportedOperationException 例外。