1. 程式人生 > >Spring基礎(20)——AOP——靜態PointCut

Spring基礎(20)——AOP——靜態PointCut

靜態切入點只在代理建立時執行一次,而不是在執行期間每次呼叫方法時都執行,所以效能比動態切入點要好,是首選的切入點方式。

在Spring中定義了兩個靜態切入點的實現類。

StaticMethodMatcherPointcut:一個抽象的靜態Pointcut,它不能被例項化。開發者可以根據自己擴充套件該類來實現自定義的切入點。

NameMatchMethodPointcut:只能對方法名進行判別的靜態Pointcut實現類。

靜態Pointcut例項:

package test.pointcut;

public class People {

	public void speak() {
		System.out.println("People Speaking");
	}
	
	public void run() {
		System.out.println("People Run");
	}
	
	public void talk() {
		System.out.println("People Talk");
	}
}
package test.pointcut;

import java.lang.reflect.Method;

import org.springframework.aop.ClassFilter;
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;

public class PeopleAdvisor extends StaticMethodMatcherPointcutAdvisor {

	@Override
	public boolean matches(Method method, Class<?> targetClass) {
		// TODO Auto-generated method stub
		return "speak".equals(method.getName());
	}

	public ClassFilter getClassFilter() {
		
		return new ClassFilter() {
			@Override
			public boolean matches(Class<?> clazz) {
				return People.class.isAssignableFrom(clazz);
			}
		};
	}
}
package test.pointcut;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class PeopleBeforeAdvice implements MethodBeforeAdvice {

	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println(target.getClass().getSimpleName() + " is " + method.getName() + " !" );
	}

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans.xsd 
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context.xsd 
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<bean id="peopleTarget" class="test.pointcut.People"></bean>
	<bean id="peopleAdvice" class="test.pointcut.PeopleBeforeAdvice"></bean>

	<bean id="people"
		class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="interceptorNames">
			<idref bean="peopleAdvisor" />
		</property>
		<property name="target" ref="peopleTarget"></property>
	</bean>
	<bean id="peopleAdvisor" class="test.pointcut.PeopleAdvisor">
		<property name="advice" ref="peopleAdvice"></property>
	</bean>
</beans>
package test.pointcut;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("spring-servlet2.xml");
		People people = (People) context.getBean("people");
		
		people.speak();
		people.talk();
		people.run();
	}

}

執行結果:

資訊: Loading XML bean definitions from class path resource [spring-servlet2.xml]
People is speak !
People Speaking
People Talk
People Run

正則表示式:

前面的方法通過方法名定義切入點,如果有多個方法需要定義切入點,需要在實現類中多次判斷,如果多個目標的名字有一定的規則,使用正則表示式過濾,將減少許多麻煩。

在Spring中,RegexpMethodPointcutAdvisor是正則表示式方法匹配的切面實現類。該類功能比較全,一般情況下,不需要擴充套件該類,因此也省去了編寫通知的麻煩。

與之前的除了配置有一定差異以外,程式碼都是一樣的。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans.xsd 
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context.xsd 
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<bean id="peopleTarget" class="test.pointcut.People"></bean>
	<bean id="peopleAdvice" class="test.pointcut.PeopleBeforeAdvice"></bean>

	<bean id="people"
		class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="interceptorNames">
			<idref bean="peopleAdvisor" />
		</property>
		<property name="target" ref="peopleTarget"></property>
	</bean>
	<bean id="peopleAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<!-- 
		
		 -->

		<property name="patterns">
			<list>
				<value>.*k</value>
			</list>
		</property>
		<property name="advice" ref="peopleAdvice"></property>
	</bean>
</beans>

執行結果:

資訊: Loading XML bean definitions from class path resource [spring-servlet2.xml]
People is speak !
People Speaking
People is talk !
People Talk
People Run

在定義切入點是經常使用的正則表示式:

符號描述例項
.匹配換行符外的所有單個字元setFoo.匹配setFooA,但不匹配setFoo或者setFooArr
+匹配+號前面的字元1次或者N次   setFoo.+匹配setFooA和setFooArr,但不匹配setFoo
*匹配*前面的字元0次或者N次setFoo.*匹配setFoo、setFooA和setFooArr
匹配?號前面的字元0次或者1次e?le?匹配angel中的el和angle中的le