AspectJ 中 within 和 withincode 指示符之间的区别

Difference between within and withincode designators in AspectJ

我是面向方面编程的新手。在这种情况下,我一直在研究一些指示符,其中我发现了两个指示符 "within" 和 "withincode"。我无法理解他们的区别。谁能用一个简单的例子解释一下?

来自AspectJ Programming Guide - Language Semantics - Pointcuts

within(TypePattern)
Picks out each join point where the executing code is defined in a type matched by TypePattern.

withincode(MethodPattern)
Picks out each join point where the executing code is defined in a method whose signature matches MethodPattern.

使用within,您只能限制为一种类型,因此在没有进一步限制的情况下,它将匹配匹配类型内的任何连接点。另一方面,使用 withincode,您可以使用一种模式将可能的匹配连接点进一步缩小到方法级别。

在我链接的页面末尾,有一个关于文档中使用的模式语法的 EBNF 摘要。

Nándor 的回答是正确的,你应该采纳+点赞。我只想添加一个 MCVE,一个简单的例子来说明他刚才解释得很好。我这样做是为了将来可能会发现这个问题的其他用户的利益,以帮助他们更好地理解这里理论上描述的内容。

驱动申请:

package de.scrum_master.app;

public class Application {
  private int id;
  private String name;

  public Application(int id, String name) {
    this.id = id;
    this.name = name;
  }

  @Override
  public String toString() {
    return "Application[id=" + id + ", name=" + name + "]";
  }

  public void printName() {
    System.out.println(this);
  }

  public static void main(String[] args) {
    new Application(11, "My application").printName();
  }
}

看点:

package de.scrum_master.aspect;

import de.scrum_master.app.Application;

public aspect WithinVsWithincodeAspect {
  before() : withincode(* Application.printName()) {
    System.out.println("[withincode] " + thisJoinPoint);
  }

  before() : within(Application) {
    System.out.println("[within]     " + thisJoinPoint);
  }
}

控制台日志:

[within]     staticinitialization(de.scrum_master.app.Application.<clinit>)
[within]     execution(void de.scrum_master.app.Application.main(String[]))
[within]     call(de.scrum_master.app.Application(int, String))
[within]     preinitialization(de.scrum_master.app.Application(int, String))
[within]     initialization(de.scrum_master.app.Application(int, String))
[within]     execution(de.scrum_master.app.Application(int, String))
[within]     set(int de.scrum_master.app.Application.id)
[within]     set(String de.scrum_master.app.Application.name)
[within]     call(void de.scrum_master.app.Application.printName())
[within]     execution(void de.scrum_master.app.Application.printName())
[withincode] get(PrintStream java.lang.System.out)
[within]     get(PrintStream java.lang.System.out)
[withincode] call(void java.io.PrintStream.println(Object))
[within]     call(void java.io.PrintStream.println(Object))
[within]     execution(String de.scrum_master.app.Application.toString())
[within]     call(java.lang.StringBuilder(String))
[within]     get(int de.scrum_master.app.Application.id)
[within]     call(StringBuilder java.lang.StringBuilder.append(int))
[within]     call(StringBuilder java.lang.StringBuilder.append(String))
[within]     get(String de.scrum_master.app.Application.name)
[within]     call(StringBuilder java.lang.StringBuilder.append(String))
[within]     call(StringBuilder java.lang.StringBuilder.append(String))
[within]     call(String java.lang.StringBuilder.toString())
Application[id=11, name=My application]

如您所见,与 withincode() 相比,within() 匹配 super-set 个连接点。当然,您可以通过 && 将两个切入点与其他切入点组合,以进一步缩小匹配的连接点集或通过 || 扩展它。当然,也可以通过 ! 排除。

请进一步注意 withincode() 匹配目标方法内部发生的事情,而不是方法执行本身。在这方面,它类似于 cflowbelow(),但它不会匹配从那里调用的方法之外的任何内容,如 cflow()cflowbelow() 那样。