SpringAOP中切入點的高級使用


上一篇 SpringAOP之使用切入點創建通知

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方法才會被通知
    }

title

二、使用組合切入點(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;
            }
        }

本項目代碼地址,覺得寫的還不錯就給個star


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM