Java 如何基于带注释的参数编写方面切入点

Java 如何基于带注释的参数编写方面切入点,java,spring,annotations,aspectj,Java,Spring,Annotations,Aspectj,我在解决如何创建一个切入点来操作具有特定注释参数的bean时遇到了一些困难。我的最终目标是在处理参数之前验证参数的值,但目前我只需要创建切入点 考虑以下注释 @Retention(RetentionPolicy.RUNTIME) @目标({ElementType.PARAMETER}) public@interface MyAnnotation{} 然后,我想将此应用于许多方法,如: public void method1(@MyAnnotation long i){} public void

我在解决如何创建一个切入点来操作具有特定注释参数的bean时遇到了一些困难。我的最终目标是在处理参数之前验证参数的值,但目前我只需要创建切入点

考虑以下注释

@Retention(RetentionPolicy.RUNTIME)
@目标({ElementType.PARAMETER})
public@interface MyAnnotation{}
然后,我想将此应用于许多方法,如:

public void method1(@MyAnnotation long i){}
public void method2(字符串someThing,@MyAnnotation long i{}
public void method3(字符串someThing,@MyAnnotation long i,byte value){}
所以

  • 我不在乎这些方法在哪个类(或包)中
  • 带注释的参数的位置将有所不同
  • 我知道带注释的值只适用于特定类型
我的切入点实现需要遵循以下原则:

@Before(value=“**(..)和&args(verifyMe)”)
公共无效验证调查ID(长验证时间){}
我对
@Before
值需要是什么以及如何连接注释及其类型感到有点困惑。在这一点上,可能不值得列出我尝试过的事情

更新:根据我在http://stackoverflow.com/questions/3565718/pointcut-matching-methods-with-annotated-parameters/3567170#3567170 (纠正了一些误解,增加了我忽略的空间)我已经达到了以下效果:

@Before(“执行(public**(..,@full.path.to.MyAnnotation(*),..)”)
public void before方法(连接点连接点){
System.out.println(“至少有一个参数用@MyAnnotation注释”);
}

这几乎就是我所需要的——我所需要做的就是将带注释的参数的值作为参数传递给方法。我不太清楚让Spring这么做的语法(链接的答案没有显示这一点)。

这就是我在摆弄它之后得出的结论(导入被省略):

不需要任何特定于Spring的内容,因为AspectJ已经为您提供了所需的参数。

与sheltem已经指出的非常类似,解决方案如下所示(这次使用注释样式语法,因为在Spring AOP中您不能使用本机AspectJ语法):

原始海报注释:

包注释;
导入java.lang.annotation.ElementType;
导入java.lang.annotation.Retention;
导入java.lang.annotation.RetentionPolicy;
导入java.lang.annotation.Target;
@保留(RetentionPolicy.RUNTIME)
@目标({ElementType.PARAMETER})
public@interface MyAnnotation{}
驱动程序应用程序:

我使用驱动程序应用程序来测试我的AspectJ解决方案。在Spring中,类和方面都需要是Springbeans/组件才能工作

package de.scrum\u master.app;
导入java.util.ArrayList;
导入java.util.HashSet;
导入java.util.List;
导入java.util.Set;
导入annotations.MyAnnotation;
公共类应用程序{
public void method1(@MyAnnotation int i){}
public void method2(字符串id,@MyAnnotation float f){}
public void method3(int i、@MyAnnotation List strings、@MyAnnotation strings){}
public void method4(int i,@MyAnnotation Set number,float f,boolean b){}
公共void方法5(布尔b,字符串s,@MyAnnotation字符串s2,浮点f,int i){}
public void notIntercepted(布尔b、字符串s、字符串s2、浮点f、int i){}
公共静态void main(字符串[]args){
列表字符串=新的ArrayList();
字符串。添加(“foo”);
字符串。添加(“条”);
Set number=新的HashSet();
增加(11);
增加(22);
增加(33);
应用程序app=新应用程序();
附录方法1(1);
附录方法2(“foo”,1f);
附录方法3(1,字符串,“foo”);
附录方法4(1,数字,1f,真);
应用方法5(假,“foo”,“bar”,1f,1);
应用程序未被拦截(假,“foo”,“bar”,1f,1);
}
}
方面:

package de.scrum\u master.aspect;
导入java.lang.annotation.annotation;
导入org.aspectj.lang.JoinPoint;
导入org.aspectj.lang.SoftException;
导入org.aspectj.lang.annotation.Aspect;
导入org.aspectj.lang.annotation.Before;
导入org.aspectj.lang.reflect.MethodSignature;
导入annotations.MyAnnotation;
@面貌
公共类ArgCatcherAspect{
@之前(“执行(公共**(..,@MyAnnotation(*),..)”)
public void InterceptMethods,其参数为NotatedParameters(JoinPoint thisJoinPoint){
System.out.println(此连接点);
MethodSignature=(MethodSignature)thisJoinPoint.getSignature();
String methodName=signature.getMethod().getName();
类[]parameterTypes=signature.getMethod().getParameterTypes();
注释[][]注释;
试一试{
annotations=thisJoinPoint.getTarget().getClass()。
getMethod(methodName,parameterTypes).getParameterAnnotations();
}捕获(例外e){
抛出新的软异常(e);
}
int i=0;
对于(对象arg:thisJoinPoint.getArgs()){
for(注释:注释[i]){
if(annotation.annotationType()==MyAnnotation.class){
System.out.println(“+annotation+”->“+arg);
//在此处验证“arg”或执行任何操作
}
}
i++;
}
}
}
控制台日志:

执行(void de.scrum_master.app.Application.method1(int))
@annotations.MyAnnotation()->1
执行(void de.scrum_master.app.Application.method2(字符串、浮点))
@安
@Aspect
public class VerifyAspect {

    @Before("execution(* *(.., @annotations.MyAnnotation (*), ..)) && args(.., verifyMe)")
    public void verifyInvestigationId(final Object verifyMe) {
        System.out.println("Aspect verifying: " + verifyMe);
    }
}