为什么这个 AspectJ 方法签名表达式匹配子类型中被覆盖的方法?

Why does this AspectJ method signature expression match overwritten methods in subtypes?

我定义了两个类

public class A{
    public A myMethod(){
        return this;
    }
}

public class B extends A{
    @Override public B myMethod(){
        return this;
    }
}

和切入点 execution(public A+ A.*(..)).

我很惊讶这两种方法都被切入点选中了。为什么我没有在 myMethod() 的定义类型的类型名称后添加加号?

如果+已经存在匹配子类型,为什么AspectJ的设计不一致?

方法执行被捕获,因为您正在拦截基 class 中定义的方法。当在 subclass 中被覆盖时,它仍然会被匹配。切入点 不会 匹配 subclass 中定义的任何方法。


让我重命名您的 classes 以使代码更具可读性,并将其变成 MCVE:

基础class:

package de.scrum_master.app;

public class Base {
  public Base baseAction() {
    return this;
  }
}

Subclass 重写方法:

package de.scrum_master.app;

public class Sub extends Base {
  @Override
  public Sub baseAction() {
    return this;
  }

  public Sub subAction() {
    return this;
  }
}

请注意,我在 subclass 中添加了另一种方法,它不包含在基础 class.

驱动申请:

package de.scrum_master.app;

public class Application {
  public static void main(String[] args) {
    new Base().baseAction();
    System.out.println("-----------------");
    new Sub().baseAction();
    System.out.println("-----------------");
    new Sub().subAction();
  }
}

看点:

package de.scrum_master.app;

import de.scrum_master.app.Base;

public aspect MyAspect {
  before() : execution(Base Base.*(..)) {
    System.out.println("Base Base.*(..)   -> " + thisJoinPoint);
  }

  before() : execution(Base+ Base.*(..)) {
    System.out.println("Base+ Base.*(..)  -> " + thisJoinPoint);
  }

  before() : execution(Base Base+.*(..)) {
    System.out.println("Base Base+.*(..)  -> " + thisJoinPoint);
  }

  before() : execution(Base+ Base+.*(..)) {
    System.out.println("Base+ Base+.*(..) -> " + thisJoinPoint);
  }
}

控制台日志:

Base Base.*(..)   -> execution(Base de.scrum_master.app.Base.baseAction())
Base+ Base.*(..)  -> execution(Base de.scrum_master.app.Base.baseAction())
Base Base+.*(..)  -> execution(Base de.scrum_master.app.Base.baseAction())
Base+ Base+.*(..) -> execution(Base de.scrum_master.app.Base.baseAction())
-----------------
Base Base.*(..)   -> execution(Sub de.scrum_master.app.Sub.baseAction())
Base+ Base.*(..)  -> execution(Sub de.scrum_master.app.Sub.baseAction())
Base Base+.*(..)  -> execution(Sub de.scrum_master.app.Sub.baseAction())
Base+ Base+.*(..) -> execution(Sub de.scrum_master.app.Sub.baseAction())
-----------------
Base+ Base+.*(..) -> execution(Sub de.scrum_master.app.Sub.subAction())

如果您还在方法签名中的 class 名称中添加 +,您能看出如何仅捕获 Sub Sub.subAction() 吗?这也是 + 的作用以及您需要它的原因的一个很好的例子。 return 类型和方法签名都需要 Base+ 才能捕获 Sub Sub.subAction()!