AspectJ - 多个@annotation切入点

时间:2014-06-09 19:06:08

标签: java annotations aspectj pointcut

我无法使用" ||"进行切入点切换运算符和多个注释。我试图为一些JBehave注释创建一个Pointcut(@Given,@ Then,@ When)。

这很好用:

    @Pointcut("@annotation(given)")
    public void jBehaveGivenPointcut(Given given) { }

如果我创建和建议它,它也有效。

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

    @Pointcut("@annotation(given) || @annotation(then) || @annotation(when) ")
    public void jBehaveGivenPointcut(Given given, Then then, When when) { }

但它不起作用,我得到一个不一致的绑定异常。我尝试了其他组合,但无法找到能够解决这个问题的组合。

3 个答案:

答案 0 :(得分:3)

你想要的是不能用这种方式完成的,因为正如错误信息所说,注释绑定是不一致的:你不能同时绑定所有三个注释,因为它们位于切入点的(可能是互斥的)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) {}
}

<强>方面:

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);
        }
    }
}

正如您所看到的,切入点仅拦截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)

答案 1 :(得分:1)

这有效:

@Component
@Aspect
@RequiredArgsConstructor
public class PermissionAspect {

    @Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
    public void getMapping(){}

    @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
    public void postMapping(){}

    @Pointcut("@annotation(org.springframework.web.bind.annotation.PutMapping)")
    public void putMapping(){}

    @Pointcut("@annotation(org.springframework.web.bind.annotation.DeleteMapping)")
    public void deleteMapping(){}

    @Around("(execution(* xx.*.controller.*.*(..))) && (getMapping() || postMapping() || putMapping() || deleteMapping())")
    Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

答案 2 :(得分:0)

一个简单的解决方案是创建多个切入点并转发到包含处理程序逻辑的通用方法:

@Pointcut("@annotation(first)")
public void onFirst(First first) {
    Common common = getCommon(first);
    handle(common);
}

@Pointcut("@annotation(second)")
public void onSecond(Second second) {
    Common common = getCommon(second);
    handle(common);
}

private void handle(Common common){...}