微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

AspectJ:声明和检索方法参数注释的切入点

如何解决AspectJ:声明和检索方法参数注释的切入点

我已阅读以下有价值的链接

考虑此请求以使用setter方法

public void setSomething(@ParameterLevel(name="abc") String something){
   this.something = something;
}

我满足以下条件并且工作正常:

@pointcut("execution(* *.*(@somepackage.ParameterLevel (*)))")
void parameterLevel01() {}

现在,我想通过以下方法的参数来检索@ParameterLevel批注:

@pointcut("execution(* *.*(@somepackage.ParameterLevel (*)))")
void parameterLevel01(ParameterLevel parameterLevel) {} <--To be used directly in the advice method

目的是在建议方法中直接使用Annotation参数如何

类似的东西,

@within(classLevel) for @ClassLevel in:

@ClassLevel
public class SomeClass {
  ...
}

@annotation(methodLevel) for @MethodLevel in

   @MethodLevel
   public void somethingTodo(){
     ...
   }

如何实现这一目标。有可能吗我正在使用AspectJ 1.9.6

解决方法

无论您使用..,@MyAnnotation (*),..还是仅使用@MyAnnotation (*)(这仅消除了可能存在多个匹配项的歧义),都没有直接方法将方法参数注释绑定到建议参数,只有方法论据本身。在AspectJ中,这没有改变。否则,您可能会在发行说明中看到它,因为它是一项新功能。

因此,您将不得不使用问题中已经链接的其他两个答案中的方法,即,手动遍历参数类型和注释。

有些离题,有一个非常古老的Bugzilla ticket #233718,它与绑定多个匹配的(带注释的)参数有关,但与绑定其注释无关。这是我最近与AspectJ维护人员Andy Clement碰到的discussion中出现的问题。但是,即使这一天实施了一天,也无法解决您的问题。

我想您可以从这里获取它,并根据链接的问题调整我的解决方案,以满足您的需求。如有任何后续问题,欢迎随时告诉我,但这应该很简单。之所以可以进行优化,是因为您知道确切的参数位置(认为是数组索引),如果您这样倾斜的话,也就是不需要遍历所有参数。


更新:给您一些MCVE。它基于this answer,并且已简化为假定注释始终位于第一个参数和第一个参数上。

请了解什么是MCVE,然后下次自己提供一个,因为这是您的工作,而不是我的。这是您的免费照片。

标记注释+驱动程序应用程序

package de.scrum_master.app;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;

@Retention(RUNTIME)
public @interface ParameterLevel {
  String name();
}
package de.scrum_master.app;

public class Application {
  public static void main(String[] args) {
    new Application().doSomething("foo");
  }

  public void doSomething(@ParameterLevel(name="abc") String string) {}
}

方面:

package de.scrum_master.aspect;

import java.lang.annotation.Annotation;

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

import de.scrum_master.app.ParameterLevel;

@Aspect
public class ParameterLevelAspect {
  @Before("execution(public * *(@de.scrum_master.app.ParameterLevel (*))) && args(string)")
  public void beforeAdvice(JoinPoint thisJoinPoint,String string) {
    System.out.println(thisJoinPoint + " -> " + string);
    MethodSignature signature = (MethodSignature) thisJoinPoint.getSignature();
    String methodName = signature.getMethod().getName();
    Class<?>[] parameterTypes = signature.getMethod().getParameterTypes();
    Annotation[] annotations;
    try {
      annotations = thisJoinPoint.getTarget().getClass()
        .getMethod(methodName,parameterTypes)
        .getParameterAnnotations()[0];
    } catch (NoSuchMethodException | SecurityException e) {
      throw new SoftException(e);
    }
    ParameterLevel parameterLevel = null;
    for (Annotation annotation : annotations) {
      if (annotation.annotationType() == ParameterLevel.class) {
        parameterLevel = (ParameterLevel) annotation;
        break;
      }
    }
    assert parameterLevel != null;
    System.out.println("  " + parameterLevel + " -> " + parameterLevel.name());
  }
}

控制台日志:

execution(void de.scrum_master.app.Application.doSomething(String)) -> foo
  @de.scrum_master.app.ParameterLevel(name="abc") -> abc

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。