Pointcut定義了Advice應用的時機,在Spring中使用PointcutAdvisor將Pointcut與Advice結合為一個物件,PointcutAdvisor為Advisor的子介面,Advisor介面於Spring中的定義如下:
package org.springframework.aop;
import org.aopalliance.aop.Advice;
public interface Advisor {
boolean isPerInstance();
Advice getAdvice();
}
PointcutAdvisor介面於Spring中的定義如下:
package org.springframework.aop;
public interface PointcutAdvisor extends Advisor {
Pointcut getPointcut();
}
Spring 中大部分內建的 Pointcut 都有對應的
PointcutAdvisor,在這邊先來介紹一下,如何使用Spring所提供的
org.springframework.aop.support.NameMatchMethodPointcutAdvisor,這是最基本的
PointcutAdvisor,它是Spring中靜態Pointcut的實例,您可以指定Advice所要應用的目標上之方法名稱,或者是用 *
來指定,例如hello*表示呼叫代理物件上以hello作為開頭的方法名稱時,都會應用指定的Advices(在這個主題之前的例子,Advice會被
套用至所有代理的方法)。
舉個實際的例子來說,假設您定義了IHello的介面:
package onlyfun.caterpillar;
public interface IHello { public void helloNewbie(String name); public void helloMaster(String name); }
接著定義HelloSpeaker類別來實作IHello介面:
package onlyfun.caterpillar;
public class HelloSpeaker implements IHello { public void helloNewbie(String name) { System.out.println("Hello, " + name + " newbie!"); } public void helloMaster(String name) { System.out.println("Hello, " + name + " master!"); } }
接著您可以撰寫一個簡單的Advice,例如這邊會使用到 Before Advice 中的 LogBeforeAdvice,接著您撰寫以下的Bean定義檔,使用NameMatchMethodPointcutAdvisor將Pointcut與Advice結合在一起:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans> <bean id="logBeforeAdvice" class="onlyfun.caterpillar.LogBeforeAdvice"/> <bean id="helloAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> <property name="mappedName"> <value>hello*</value> </property> <property name="advice"> <ref bean="logBeforeAdvice"/> </property> </bean> <bean id="helloSpeaker" class="onlyfun.caterpillar.HelloSpeaker"/> <bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> <value>onlyfun.caterpillar.IHello</value> </property> <property name="target"> <ref bean="helloSpeaker"/> </property> <property name="interceptorNames"> <list> <value>helloAdvisor</value> </list> </property> </bean> </beans>
在NameMatchMethodPointcutAdvisor
的"mappedName"屬性上,由於指定了"hello*",所以當呼叫helloNewbie()或helloMaster()方法時,由於方法名
稱的開頭符合"hello",就會應用logBeforeAdvice的服務邏輯,可以撰寫以下的程式來進行測試,看看結果是否符合預期:
package onlyfun.caterpillar;
import org.springframework.context.ApplicationContext; import org.springframework.context. support.FileSystemXmlApplicationContext;
public class SpringAOPDemo { public static void main(String[] args) { ApplicationContext context = new FileSystemXmlApplicationContext( "beans-config.xml"); IHello helloProxy = (IHello) context.getBean("helloProxy");
helloProxy.helloNewbie("Justin"); helloProxy.helloMaster("caterpillar"); } }
|