Spring AOP 剖析(6)

Spring AOP 的底層實現機制

 

 

 

2.  Spring AOP 中的 Pointcut

 

6.  擴展 Pointcut

 

如何前面的 Pointcut 類型都無法滿足要求,這種情況下可以擴展 Spring AOP 的 Pointcut ,給出自定義的 Pointcut。

 

要自定義 Pointcut ,Spring AOP 已經提供了相應的擴展抽象支持,我們只需要繼承相應的抽象父類,然後實現或者覆寫

 

方法邏輯即可。

 

Spring AOP 的 Pointcut 類型可以劃分爲  StaticMethodMatcherPointcut 和 DynamicMethodMatcherPointcut

 

自定義 Pointcut 只需要在這兩個抽象類的基礎上實現相應子類即可。

 

 


a. StaticMethodMatcherPointcut

 

package org.springframework.aop.support;

import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;

/**
 * 因爲是 StaticMethodMatcher,所以其 MethodMatcher 的 isRuntime 方法返回 false,
 * 同時三個參數的 matches 方法拋出 UnsupportedOperationException 異常,
 * 以表示該方法不應該被調用到。(該部分在 抽象父類 StaticMethodMatcher 中實現)
 *
 */
public abstract class StaticMethodMatcherPointcut extends StaticMethodMatcher implements Pointcut {

	private ClassFilter classFilter = ClassFilter.TRUE;


	/**
	 * 默認子類的 ClassFilter 均爲 ClassFilter.TRUE,即忽略類的類型匹配。
	 */
	public ClassFilter getClassFilter() {
		return this.classFilter;
	}
	
	/**
	 * 如果子類需要對目標對象的類型做進一步的限制,可以通過該方法設置相應的 ClassFilter 實現
	 * @param classFilter
	 */
	public void setClassFilter(ClassFilter classFilter) {
		this.classFilter = classFilter;
	}

	public final MethodMatcher getMethodMatcher() {
		return this;
	}

}

 

最終實現 自定義的StaticMethodMatcherPointcut 只需要實現兩個參數的 matches 方法即可。

 

例如:提供一個 Pointcut , 用來撲捉系統中數據訪問對象中的查詢方法。

 

package prx.aop.pointcut;

import java.lang.reflect.Method;

import org.springframework.aop.support.StaticMethodMatcherPointcut;

public class QueryMethodPointcut extends StaticMethodMatcherPointcut {

	public boolean matches(Method method, Class<?> targetClass) {
		return method.getName().startsWith("query") 
				&& targetClass.getPackage().getName().contains("dao");
	}

}

 

b. DynamicMethodMatcherPointcut

 

package org.springframework.aop.support;

import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;

/**
 * 因爲是 DynamicMethodMatcher,所以其 MethodMatcher 的 isRuntime 方法返回 true,
 * 同時兩個參數的 matches 也返回 true,以便三個參數的方法順利執行
 * (該部分在 抽象父類 DynamicMethodMatcher 中實現)
 */
public abstract class DynamicMethodMatcherPointcut extends DynamicMethodMatcher implements Pointcut {

	/**
	 * 默認子類的 ClassFilter 均爲 ClassFilter.TRUE,即忽略類的類型匹配。
	 * 如果需要特定的目標對象類型限定,需要覆蓋這個方法。
	 */
	public ClassFilter getClassFilter() {
		return ClassFilter.TRUE;
	}

	public final MethodMatcher getMethodMatcher() {
		return this;
	}

}

 

最終實現自定義的 DynamicMethodMatcherPointcut 只需要實現三個參數的 matches 方法即可。

 

例如:有個查詢只有 Boss 才能訪問。

 

package prx.aop.pointcut;

import java.lang.reflect.Method;

import org.springframework.aop.support.DynamicMethodMatcherPointcut;

public class BossQueryMethodPointcut extends DynamicMethodMatcherPointcut {

	public boolean matches(Method method, Class<?> targetClass, Object[] args) {
		if(method.getName().startsWith("query") 
				&& targetClass.getPackage().getName().contains("dao")) {
			if(args != null && args.length > 1) {
				return "Boss".equals(args[0]);
			}
		}
		return false;
	}

}

 

如果願意,也可以覆蓋 兩個參數的 matches 方法,這樣,不用每次都得到三個參數的 matches 方法執行的時候才檢查

 

所有的條件。

 


將 Pointcut 加入 IoC 容器中

 

選擇好了 Pointcut ,剩下就是 將它們加入Spring IoC 容器中,以便 Spring 管理。 Spring 中的 Pointcut 實現都是

 

普通的 Java 對象, 所以想普通的 POJO 那樣配置注入就可以了。

 

<bean id="nameMatchPointcut" class="org.springframework.aop.support.NameMatchMethodPointcut">
	<property name="mappedNames">
		<list>
			<value>methodName1</value>
			<value>methodName2</value>
		</list>
	</property>
</bean>
 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章