如果我们需要根据方法的参数不同而决定事都进行切入,而不是不管方法是什么参数全部切入的话,我们就需要使用动态切入点,在每次方法调用时候都进行检查(确切的说是参数检查),;来决定是否执行通知
BeanOne.java
package DynamicPointCutAdvisor; public class BeanOne ... { public void foo() ... { System.out.println( " foo-one " ); } public void bar() ... { System.out.println( " bar-one " ); } public void dynamic( int x) ... { System.out.println(x); } }动态切入点:
package DynamicPointCutAdvisor; import java.lang.reflect.Method; import org.springframework.aop.ClassFilter; import org.springframework.aop.support.DynamicMethodMatcherPointcut; public class SimpleDynamicPointcut extends DynamicMethodMatcherPointcut ... { // 静态方法检查,为避免每次调用bar方法是都进行一次检测,导致效率降低 public boolean matches(Method method, Class cls) ... { return " dynamic " .equals(method.getName()); } // 当参数不为100时候,进行切入 public boolean matches(Method method, Class cls, Object[] obj) ... { int x = ((Integer)obj[ 0 ]).intValue(); return (x != 100 ); } public ClassFilter getClassFilter() ... { return new ClassFilter() ... { public boolean matches(Class cls) ... { return cls == BeanOne. class ; } } ; } }环绕通知:
package DynamicPointCutAdvisor; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class SimpleAdvise implements MethodInterceptor ... { public Object invoke(MethodInvocation invocation) throws Throwable ... { System.out.println( " before " ); Object retVal = invocation.proceed(); System.out.println( " after " ); return retVal; } }测试代码:
package DynamicPointCutAdvisor; import org.aopalliance.aop.Advice; import org.springframework.aop.Advisor; import org.springframework.aop.Pointcut; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.support.DefaultPointcutAdvisor; public class Test ... { /** */ /** * @param args */ public static void main(String[] args) ... { BeanOne one = new BeanOne(); BeanOne proxyOne; Pointcut pc = new SimpleDynamicPointcut(); Advice advice = new SimpleAdvise(); Advisor advisor = new DefaultPointcutAdvisor(pc,advice); // 创建BeanOne代理 ProxyFactory pf1 = new ProxyFactory(); pf1.addAdvisor(advisor); pf1.setTarget(one); proxyOne = (BeanOne)pf1.getProxy(); proxyOne.dynamic( 100 ); System.out.println( " ------------------- " ); proxyOne.dynamic( 101 ); System.out.println( " ------------------- " ); proxyOne.bar(); } }运行结果:
100 ------------------- before 101 after ------------------- bar-one
后记
如果我们在切入点类中的方法检查代码中加入提示,如:
package DynamicPointCutAdvisor; import java.lang.reflect.Method; import org.springframework.aop.ClassFilter; import org.springframework.aop.support.DynamicMethodMatcherPointcut; public class SimpleDynamicPointcut extends DynamicMethodMatcherPointcut ... { // 静态方法检查,为避免每次调用bar方法是都进行一次检测,导致效率降低 public boolean matches(Method method, Class cls) ... { System.out.println( " static check for " + method.getName()); return " dynamic " .equals(method.getName()); } // 当参数不为100时候,进行切入 public boolean matches(Method method, Class cls, Object[] obj) ... { System.out.println( " dynamic check for " + method.getName()); int x = ((Integer)obj[ 0 ]).intValue(); return (x != 100 ); } public ClassFilter getClassFilter() ... { return new ClassFilter() ... { public boolean matches(Class cls) ... { return cls == BeanOne. class ; } } ; } }可以看到结果如下:
static check for dynamic static check for bar static check for foo static check for clone static check for toString static check for dynamic dynamic check for dynamic 100 ------------------- dynamic check for dynamic before 101 after ------------------- static check for bar bar-one
可以看到,红色部分代表静态方法类型检查,绿色代表动态方法类型检查
当我们实现了静态检查|(public boolean matches(Method method, Class cls) )时候,动态类型对不匹配的方法,如本例中的bar不再进行动态检查,提高了效率,如果没有public boolean matches(Method method, Class cls) 方法,则所有方法势必都会进行类型检查,不仅降低效率,还有可能因为方法参数的不同导致异常(如bar是没有参数的,使用动态检查中的 int x=((Integer)obj[0]).intValue();就会出现异常)