静态切入点只在代理创建时执行一次,而不是在运行期间每次调用方法时都执行,所以性能比动态切入点要好,是首选的切入点方式。
在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 |