、Spring AOP Pointcut
以上只是Advice,如果不指定切入点,Spring 则使用所有可能的Jointpoint进行织入(当然如果你在Advice中进行方法检查除外)。因此切入点在AOP中扮演一个十分重要的角色。Spring 2.0 推荐使用AspectJ的Annocation的切入点表达式来定义切入点,或者使用<aop:xxx/>来定义AOP,这方面本篇不做考虑。
1、Pointcut:它是Spring AOP Pointcut的核心,定义了getClassFilter()和getMethodMatcher()两个方法。
2、ClassFilter:定义了matches(Class clazz)一个方法。
3、MethodMatcher() 定义了matches(Method,Class),isRuntime(),matches(Mathod,Class,Object[])三个方法,如果isRuntime()返回true则表示为动态代理(实际是动态代理的动态代理),则调用第三个方法(每访问一次调用一次),否则调用第一个方法(并且只调用一次)
例子:
//业务逻辑接口
package study.spring.lesson04.advice;
public interface ILogin {
boolean login(String username,String password);
}
//目标类,包含了核心业务逻辑
package study.spring.lesson04.advice;
public class LoginAction implements ILogin{
public boolean login(String username, String password) {
if ("zhangsan".equals(username))
throw new RuntimeException();
else if ("lisi".equals(username) && "1234".equals(password))
return true;
else
return false;
}
}
//实现ClassFilter接口
package study.spring.lesson04.pointcut;
import org.springframework.aop.ClassFilter;
import study.spring.lesson04.advice.ILogin;
public class MyClassFilter implements ClassFilter { //实现ClassFilter
public boolean matches(Class clazz) {
if (ILogin.class.isAssignableFrom(clazz)) //设置用用通知的类
return true;
else
return false;
}
}
//实现MethodMatcher接口
package study.spring.lesson04.pointcut;
import java.lang.reflect.Method;
import org.springframework.aop.MethodMatcher;
import study.spring.lesson04.advice.ILogin;
public class MyMethodMatcher implements MethodMatcher { //实现 MethodMatcher 接口
public boolean isRuntime() {
return false;
}
public boolean matches(Method method, Class clazz) { //设置应用通知的方法
if ("login".equals(method.getName())
&& ILogin.class.isAssignableFrom(clazz))
return true;
else
return false;
}
public boolean matches(Method arg0, Class arg1, Object[] arg2) {
return false;
}
}
//实现PointCut接口
package study.spring.lesson04.pointcut;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
public class MyPointcut implements Pointcut { //实现Pointcut接口
public ClassFilter getClassFilter() {
return new MyClassFilter();
}
public MethodMatcher getMethodMatcher() {
return new MyMethodMatcher();
}
}
//实现PointCutAdvisor接口
package study.spring.lesson04.pointcut;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import study.spring.lesson04.advice.LoginAroundAdvice;
public class MyAdvisor implements PointcutAdvisor {
public Pointcut getPointcut() {
return new MyPointcut();
}
public Advice getAdvice() {
return new LoginAroundAdvice();
}
public boolean isPerInstance() {
return false;
}
}
//XML代码
<?xml version="1.0" encoding="GBK" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="loginTarget"
class="study.spring.lesson04.advice.LoginAction" />
<bean id="loginBeforeAdvice"
class="study.spring.lesson04.advice.LoginBeforAdvice" />
<bean id="login"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="loginTarget" />
</property>
<property name="proxyInterfaces">
<value>study.spring.lesson04.advice.ILogin</value>
</property>
<property name="interceptorNames">
<list>
<!-- <value>loginBeforeAdvice</value>
<value>LoginAfterAdvice</value>
<value>LoginAroundAdvice</value> -->
<value>MyAdvisor</value>
</list>
</property>
</bean>
<bean id="LoginAfterAdvice"
class="study.spring.lesson04.advice.LoginAfterAdvice" />
<bean id="LoginAroundAdvice"
class="study.spring.lesson04.advice.LoginAroundAdvice" />
<bean id="MyAdvisor"
class="study.spring.lesson04.pointcut.MyAdvisor " />
</beans>
4、Spring AOP 静态切入点的几个实现。
ComposablePointcut 太复杂一个切入点无法表达就用这个,union MethodMatcher和ClassFilter或者intersection MethodMatcher、ClassFilter和Pointcut。为什么不实现union Pointcut? 而只能通过Pointcuts类对Pointcut进行union操作。
ControlFlowPointcut 想对程序的运行过程进行追踪就用这个
DynamicMatchMatcherPointcut 想用动态AOP 就用这个
JdkRegexpMethodPointcut 想使用正则表达式就用这个
Perl5RegexpMethodPointcut
NameMatchMethodPointcut 想用方法名字来匹配就用这个
StaticMethodMatcherPointcut 静态切入点就用这个
没有人反对你直接实现Pointcut:)。