ITEEDU

NameMatchMethodPointcutAdvisor

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 的介面:

•      IHello.java
package onlyfun.caterpillar;
public interface IHello {
	public void helloNewbie(String name);
	public void helloMaster(String name);
}

接着定义 HelloSpeaker 类别来实作 IHello 介面:

•      HelloSpeaker.java
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结合在一 起:

•      beans‐config.xml
<?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 的服务逻辑,可以撰写以下的程式来进行测试,看看结果是否符合预期:

•      SpringAOPDemo.java
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");
	}
}