关于Spring的ControlFlowPointcut的效率问题

       利用Spring的AOP支持,可以在方法调用前后,或者在抛出异常时执行一些额外的代码。

       以上特性不过是代理模式的灵活使用而已,理解起来比较自然,没有太大难度。

       而关于ControlFlowPointcut这个特性,也就是传说中的“控制流切入点”,这个特性理解起来颇有一些意思,今天搞了一个下午,终于搞明白了这里的运行原理,记录一下备忘。

       林信良的《Spring2.0技术手册》里面4.3.3节有一个例子,我看到网上很多人说这个例子有错误,实际上这个例子完全正确,没有任何错误。

       举例来说:

       

public class A{
    public void hello(){
            System.out.println("A says:hello...");
    }
}

public class B{
    private A a;

    public void setA(A a){
        this.a=a;
    }

    public void bSayHello(){
        a.hello();
    }
}

public class Test(){
    public static void main(String[] args){
        A a=new A();
        a.hello();//第一处
        
        B b=new B();
        b.setA(a);
        b.bSayHello();//第二处
    }
}

   

         ControlFlowPointcut要实现的目的是:第一处不执行其它动作(比如在hello()方法的调用前后利用logger记录日志);而第二处可以根据Spring的配置文件执行一些其它的动作。

        那么,这里的问题是,Spring是怎么知道hello()方法是从哪儿被调用的呢?

        唯一可能的解释就是,当hello()方法被调用的时候,Spring取得了方法的调用堆栈,然后在堆栈里面去匹配,看看方法是从哪个类调用进来的。来翻spring-core***.jar里面ControlFlowFactory.java的一段源码:

       
关于Spring的ControlFlowPointcut的效率问题_第1张图片
 

        好吧,啥也不说了。。。

        如此猥琐的手法都搞出来了,为了搞明白某个方法是从哪个类中的哪个方法进行调用的,居然自己手动创建了Throwable()对象,然后通过getStackTrace()拿到调用栈!!!

        这还没完,拿到调用栈之后然后再用for循环去进行字符串匹配!!!

        显而易见,这种处理手法相当猥琐,并且运行效率显然比较低下。

        看来大牛们一直说尽量避免使用ControlFlowPointcut还是有几份道理的啊(据说运行效率会降低5到10倍---因为Spring自己在调用栈里面倒腾),佩服佩服!

        谨记之,以供同仁参考。

你可能感兴趣的:(spring,AOP)