SpringAOP中切点的高级使用
一、使用控制流切入点(ControlFlowPointcut)
什么是控制流切入点呢?看下面的代码(为了方便,就写进了一个公共类)
class Cat { public void talk() { System.out.println("I am a cat"); } public void play() { System.out.println("I am palying"); } } class BlackCat { public void sleep(Cat cat) { cat.play(); System.out.println("I am a blackCat , I am sleeping"); } } /** * 创建前置通知类 */ class BeforeAdvice implements MethodBeforeAdvice{ @Override public void before(Method method, Object[] objects, @Nullable Object o) throws Throwable { System.out.println("这个方法被通知了"+method); } }
- 需求:我们要给Cat的play()方法进行通知,但是呢,并不是说在调用play()方法的任何时候都通知, 只要在blackCat的sleep()方法中调用play()方法时才通知,也就是说:
public static void main(String[] args) { Cat cat = new Cat(); cat.play();//这个调用不会被通知 BlackCat blackCat = new BlackCat(); blackCat.sleep(cat);//这个方法中调用的paly方法才会被通知 }
创建一个ControlFlowPointcut的切入点
public static void main(String[] args) { // Cat cat = new Cat(); // cat.play();//这个调用不会被通知 // // BlackCat blackCat = new BlackCat(); // blackCat.sleep(cat);//这个方法中调用的paly方法才会被通知 Cat target = new Cat(); //第一个参数是当前就是的执行要被通知的方法的类,第二个就是的执行要被通知的方法的方法名 Pointcut pc = new ControlFlowPointcut(BlackCat.class, "sleep"); Advisor advisor = new DefaultPointcutAdvisor(pc, new BeforeAdvice()); ProxyFactory proxy = new ProxyFactory(); proxy.setTarget(target); proxy.addAdvisor(advisor); Cat proxyCat = (Cat) proxy.getProxy(); proxyCat.play();//这个方法不会被通知 System.out.println("----------------"); BlackCat blackCat = new BlackCat(); blackCat.sleep(proxyCat);//这个方法中调用的paly方法才会被通知 }
二、使用组合切入点(ComposablePointcut)
所谓组合切入点就是利用逻辑关系(or 和 and)来对切入点进行组合,比如上一文中说过的那几种切入点,使用逻辑关系写在一起就可以了。但是并不是直接和切入点来组合,而是组合切入点中的
ClassFilter和MethodMatcher
(为什么是这样?在这篇文章看一下Pointcut类的源码,就明白了)
用法:
ComposablePointcut的union()表示“或”
ComposablePointcut的intersection()表示“和”- 先定义三个MethodMatcher类
/** * 匹配sleep方法名 */ class SleepMethodMatcher extends StaticMethodMatcher{ @Override public boolean matches(Method method, Class<?> aClass) { return method.getName().equals("sleep"); } } /** * 匹配s开头 */ class SStartMethodMatcher extends StaticMethodMatcher{ @Override public boolean matches(Method method, Class<?> aClass) { return method.getName().startsWith("s"); } } /** * 匹配k结尾 */ class KEndMethodMatcher extends StaticMethodMatcher{ @Override public boolean matches(Method method, Class<?> aClass) { return method.getName().endsWith("k"); } }
- 创建切入点
/** * 创建前置通知类 */ class BeforeAdviceDemo implements MethodBeforeAdvice { @Override public void before(Method method, Object[] objects, @Nullable Object o) throws Throwable { System.out.println("这个方法被通知了" + method); } }
- 测试类
public static void main(String[] args) { Cat target = new Cat(); //这个构造方法要传入的是一个classFilter和methodMatcher实例 ComposablePointcut pc = new ComposablePointcut(ClassFilter.TRUE, new KEndMethodMatcher()); // pc.union(new SStartMethodMatcher());//匹配s开头的方法,和上边的切点是或的关系 // pc.intersection(new SleepMethodMatcher()); //匹配sleep方法,和上边切点是和的关系 Advisor advisor = new DefaultPointcutAdvisor(pc,new BeforeAdviceDemo()); ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTarget(target); proxyFactory.addAdvisor(advisor); Cat cat = (Cat) proxyFactory.getProxy(); cat.talk(); }
上边的这个ClassFilter.TRUE 和下边代码其实是一样的,意思就是返回的classFilter为true,也就是匹配所有类
new ClassFilter() { @Override public boolean matches(Class<?> aClass) { return true; } }
来源:https://www.cnblogs.com/Lyn4ever/p/12020057.html