java - 在 aspectj 中使用 cflow() 时如何删除 java..* 调用?

标签 java aspectj

我在以下示例代码中发现了我的问题。 HelloWorld 类是我的源代码,需要由 HelloWorldTracer 方面进行检测。我的目标是找到 HelloWorld.main() 控制流中的所有方法调用。但我对与包 java.lang.* 中的任何类型相关的方法调用不感兴趣(例如:java.lang.StringBuilder)。

package com.abc;

public class HelloWorld {

    public static void main(String args[]) {
        StringBuilder str = new StringBuilder();
        str.toString();
        Sample.testMethod();
    }
}

package com.abc;

public class Sample {

    public static void testMethod()
    {
        StringBuilder str = new StringBuilder();
        str.toString(); 
    }

}


public aspect HelloWorldTracer {

    pointcut helloWorldTracker() : 
        execution(* com.sybase.HelloWorld.main(..)) && within(com.abc..*) &&  !within(HelloWorldTracer);

    pointcut methodTracker():
         cflow(helloWorldTracker()) 
         && !within(java.lang..*) && !within(HelloWorldTracer);

    Object around(): methodTracker()
    {

        System.out.println("Inside advice..." + thisJoinPointStaticPart.getSignature().toString() );
        Object o = proceed();
        return o;
    }

}

即使 !within(java.lang..*) 已在 methodTracker 中明确指定,也使用上面提到的切入点 StringBuilder 类型() 切入点。我也尝试了 !within(java.lang.StringBuilder)!execution(String java.langStringBuilder.toString(..)),但没有成功。任何帮助限制来自 java.lang..* 的类型的建议都将不胜感激。

最佳答案

Nitzan Volman 的建议不是您想要的。

首先,在您的代码示例中,您可能想要更改

execution(* com.sybase.HelloWorld.main(..))

execution(* com.abc.HelloWorld.main(..))

修复该问题后,您会收到很多警告,因为您正尝试使用 around()< 来建议 initialization()preinitialization() 切入点 由于编译器的限制,这是不可能的。

然后当您将输出行更改为 just

System.out.println(thisJoinPointStaticPart);

您将看到您的代码中真正发生了什么:

execution(void com.abc.HelloWorld.main(String[]))
call(java.lang.StringBuilder())
call(String java.lang.StringBuilder.toString())
call(void com.abc.Sample.testMethod())
staticinitialization(com.abc.Sample.<clinit>)
execution(void com.abc.Sample.testMethod())
call(java.lang.StringBuilder())
call(String java.lang.StringBuilder.toString())

即您不仅仅是拦截方法调用(或者您的意思是捕获方法执行,这不一样吗?),而是所有(嗯,很多)种类的连接点。试试这个:

public aspect HelloWorldTracer {
    pointcut belowHelloWorldMain() :
        cflow(execution(* com.abc.HelloWorld.main(..)));

    pointcut methodTracker():
        belowHelloWorldMain() &&
        call(* *(..)) &&
        !call(* java.lang..*(..)) &&
        !within(HelloWorldTracer);

    Object around(): methodTracker() {
        System.out.println(thisJoinPointStaticPart);
        return proceed();
    }
}

结果:

call(void com.abc.Sample.testMethod())

以防万一你只想拦截(而不是调用)你自己的(编织的)类的执行,它甚至更简单,因为这样你就不需要排除 Java 类:

public aspect HelloWorldTracer {
    pointcut belowHelloWorldMain() :
        cflow(execution(* com.abc.HelloWorld.main(..)));

    pointcut methodTracker():
        belowHelloWorldMain() &&
        execution(* *(..));

    Object around(): methodTracker() {
        System.out.println(thisJoinPointStaticPart);
        return proceed();
    }
}

结果:

execution(void com.abc.HelloWorld.main(String[]))
execution(void com.abc.Sample.testMethod())

如您所见,现在甚至包括 main(..)

关于java - 在 aspectj 中使用 cflow() 时如何删除 java..* 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7808700/

相关文章:

Java Arraylist 已满但不更新?

java - 被Android访问控制机制搞糊涂了。它与 Java 不同

spring - Gradle 1.0 +Spring + AspectJ 构建问题

spring - Aspectj - 拦截 HTTP 请求

java - 如何检测/建议 Spring Data (JPA) 存储库?

gradle - jacoco代码覆盖率和aspectJ编织

java - 日期格式 JSON

java - java将mp3转换为wav 16位单声道

java - 如何使用aspectj获取封闭类型

java - Tomcat Java Memory 选项保存在哪个文件中