【问题标题】:AspectJ - Multiple @annotation PointcutAspectJ - 多个@annotation 切入点
【发布时间】:2014-06-09 19:06:08
【问题描述】:

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

这很好用:

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

如果我围绕它创建和建议,它也可以工作。

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

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

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

【问题讨论】:

    标签: java annotations aspectj pointcut


    【解决方案1】:

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

    【讨论】:

    • 为什么投反对票?答案是正确的。即使不是这样,投反对票也会保留给草率的答案,表明严重缺乏研究或努力。
    【解决方案2】:

    这行得通:

    @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 {
    

    【讨论】:

      猜你喜欢
      • 2019-01-05
      • 2019-12-07
      • 1970-01-01
      • 2015-10-25
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 2015-11-06
      • 2011-05-23
      相关资源
      最近更新 更多