如何解决AspectJ:声明和检索方法参数注释的切入点
我已阅读以下有价值的链接:
- Spring AOP pointcut for annotated argument
- How to write an Aspect pointcut based on an annotated parameter
- AspectJ pointcut expression match parameter annotations at any position
考虑此请求以使用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 举报,一经查实,本站将立刻删除。