java - AspectJ join 只指向通知 "boundary"执行和调用

标签 java aspectj pointcut

1) 是否可以仅使用切入点定义(即不使用建议内的额外 Java 代码)来拦截(从外部到内部)一组类(或可能是一个包,但不能是子包)的执行(或调用)和外部调用(从这些类到该组类之外),但不能拦截“内部”执行/调用(从该组的任何类到同一组的任何类)? 2)是否可以将该组指定到要在运行时加载的外部文件中(加载时编织)?

我想要编写一个工具来在运行时应用给定的方面,但开发人员可以在 JVM 启动时指定一组类(命令行或文本文件)。

我已经设法在建议中使用额外的 Java 反射代码实现了第 1 点,但它并不理想(慢),而且我不确定是否可以从外部文件加载类/包名称并让 AspectJ 应用它们:

private static final String PACKAGE_REGEX = "com.advisethispackage..*";
private static final String BEFORE_EXECUTION_AND_NEW_INVOCATION_FILTER = "((execution(* *(..))) || (execution(*.new(..)))) && within(" + PACKAGE_REGEX + ")";
private static final String CALL_INVOCATION_FILTER = "((call(* *(..))) || (call(*.new(..)))) && within(" + PACKAGE_REGEX + ")";

我尝试过使用 insidecode (显然我还没有真正理解),或者以这种方式排除调用...

private static final String CALL_INVOCATION_FILTER = "((call(* *(..))) || (call(*.new(..)))) && (!call(* " + WITHIN_REGEX + "(..))) && (!call(" + WITHIN_REGEX + ".new(..))) && within(" + WITHIN_REGEX + ")";

...但未能排除一些同级调用。有什么想法吗?

我的 aop.xml 文件如下所示:

<aspectj>
  <aspects>
    <aspect name="org.my.aspects.RecordingAspect"/>
    <include within="org..*"/>
  </aspects>

  <weaver options="-verbose -debug -showWeaveInfo">
    <include within="com.advisethispackage..*"/>
    <include within="org.my.aspects..*"/>
  </weaver>
</aspectj>

我对 AOP 很陌生,只知道 AspectJ,并且只使用注释,而不使用 AspectJ 编译器或 AJDT。 我正在将方面j-1.8.6 与 Java 8 结合使用。

<小时/>

示例:我有 4 个类(class)(A、B、C、D)。 A 调用 B 上的方法,并调用 C,后者调用 D。B 和 C 是我想要建议的类(com.advisethispackage.B、com.advisethispackage.C),但 A 和 D 不是(com.dontadvisethispackage.A、com.dontadvisethispackage.D)。我的 RecordingAspect 建议只是打印出“在类 'X' 上调用方法”或“从类 'X' 调用到类 'Y' 的方法”。

录制时,我想输出为:

Invoked method on class 'B'
Invoking method from class 'C' to class 'D'

没有别的了。 我还记录了“之后”的时刻,这将打印...

Returning from invocation of method on class 'D' called by class 'C'
Returning from invocation of method on class 'B'

...但我认为切入点定义应该是相同的。

谢谢

最佳答案

不知道您是否已经找到了这个,但这是我为匹配您的情况而调整的两个切入点(使用 AspectJ 注释)

@Pointcut("call(* com.advisethispackage..*.*(..)) && !withincode(* com.advisethispackage..*.*(..))")
public void callFromOutsideToInside() {}

@Before("call(* (!com.advisethispackage..*).*(..)) && withincode(* com.advisethispackage..*.*(..))")
public void callFromInsideToOutside() {}

如果您还想匹配构造函数:

@Pointcut("call(com.advisethispackage..*.new(..)) && !withincode(* com.advisethispackage..*.*(..))")
public void callFromOutsideToInside() {}

@Before("call((!com.advisethispackage..*).new(..)) && withincode(* com.advisethispackage..*.*(..))")
public void callFromInsideToOutside() {}

关于java - AspectJ join 只指向通知 "boundary"执行和调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32538441/

相关文章:

java - 定义切入点以捕获接口(interface)但不捕获父接口(interface)或子接口(interface)

java - 如何在 Google Code Jam 中使用 .in 文件作为 eclipse 的输入?

java - 安卓 Java : AlertDialog method called from another class causes null pointer exception

spring - 从 ProceedingJoinPoint 获取 java.lang.reflect.Method?

java - AspectJ - 多个@annotation切入点

java - Spring AOP 切入点表达式中包名称的通配符支持

java - 解码 XML 数据中的 <br/>

java - Android Studio App播放声音

java - 如何更改由相同注释(例如 AspectJ 中的 @Around)注释的两个或多个建议的执行顺序?

java - 获取 Java 类加载引用层次结构