AspectJ - 多个@annotation 切入点

use*_*501 3 java annotations aspectj pointcut

我无法使用“||”进行切入点 运算符和多个注释。我正在尝试为一些 JBehave 注释(@Given、@Then、@When)创建切入点。

这工作正常:

    @Pointcut("@annotation(given)")
    public void jBehaveGivenPointcut(Given given) { }
Run Code Online (Sandbox Code Playgroud)

如果我围绕它创造并提出建议,它也会起作用。

为这三个注释创建切入点的语法是什么?由于我在其他切入点中使用了逻辑 OR 运算符,因此我认为它类似于:

    @Pointcut("@annotation(given) || @annotation(then) || @annotation(when) ")
    public void jBehaveGivenPointcut(Given given, Then then, When when) { }
Run Code Online (Sandbox Code Playgroud)

但它不起作用,我收到不一致的绑定异常。我尝试了其他组合,但找不到有效的组合。

kri*_*aex 5

你想要的不能用这种方式完成,因为正如错误消息所述,注释绑定不一致:你不能同时绑定所有三个注释,因为它们位于切入点的(可能互斥的)OR部分中,即通常只其中的一个可以绑定(除非您将多个注释分配给同一个方法)。您的期望可能是 AspectJ 可以通过仅分配null给另外两个(如果其中一个已绑定)来处理这种不一致,但这不是编译器现在的工作方式。

我可以提供一种解决方法,其中涉及反射而不是使用@annotation()绑定。

驱动程序应用:

package de.scrum_master.app;

import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;

public class Application {
    public static void main(String[] args) {
        doGiven("foo");
        doSomething("bar");
        doWhen(11);
        doSomethingElse(22);
        doThen();
    }

    @Given("an input value") public static void doGiven(String string) {}
    @When("I do something") public static void doWhen(int i) {}
    @Then("I should obtain a result") public static boolean doThen() { return true; }
    public static void doSomething(String string) {}
    public static void doSomethingElse(int i) {}
}
Run Code Online (Sandbox Code Playgroud)

方面:

package de.scrum_master.aspect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

@Aspect
public class JBehaveInterceptor {
    @Pointcut("execution(@org.jbehave.core.annotations.* * *(..))")
    public void jBehavePointcut() {}

    @Before("jBehavePointcut()")
    public void jBehaveAdvice(JoinPoint.StaticPart thisJoinPointStaticPart) {
        Method method = ((MethodSignature) thisJoinPointStaticPart.getSignature()).getMethod();
        for (Annotation jBehaveAnnotation : method.getAnnotations()) {
            if (jBehaveAnnotation.annotationType().getPackage().getName().equals("org.jbehave.core.annotations"))
                System.out.println(thisJoinPointStaticPart + " -> " + jBehaveAnnotation);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,切入点仅拦截所注释的方法,从而org.jbehave.core.annotations.*大大缩小了切入点匹配的范围 - 不仅仅是@Given, @When, @Then,但也许这正是您想要的,因为 JBehave 提供的注释不仅仅是这些注释。

在建议中,我们循环遍历所有方法注释,因为可能不仅仅是 JBehave 注释。如果任何注释包名称与相应的 JBehave 包匹配,我们就会执行某些操作(在本例中将注释打印到标准输出)。

我希望这能解决您的问题。我无法为您扩展 AspectJ 语言,这是我能想到的最好的。无论如何,这会产生以下输出:

execution(void de.scrum_master.app.Application.doGiven(String)) -> @org.jbehave.core.annotations.Given(priority=0, value=an input value)
execution(void de.scrum_master.app.Application.doWhen(int)) -> @org.jbehave.core.annotations.When(priority=0, value=I do something)
execution(boolean de.scrum_master.app.Application.doThen()) -> @org.jbehave.core.annotations.Then(priority=0, value=I should obtain a result)
Run Code Online (Sandbox Code Playgroud)

  • 为什么投反对票?答案是正确的。即使不是,反对票也会保留给草率的答案,表明严重缺乏研究或努力。 (2认同)