Java 带注释参数的切入点匹配方法

Java 带注释参数的切入点匹配方法,java,parameters,annotations,aop,aspectj,Java,Parameters,Annotations,Aop,Aspectj,我需要创建一个切入点与方法匹配的方面,如果: 它是用MyAnnotationForMethod注释的 它的一个参数(可以有多个)用@MyAnnotationForParam注释(但也可以有其他注释) aspect类如下所示 @Pointcut("execution(@MyAnnotationForMethod * *(..,@aspects.MyAnnotationForParam Object, ..)) && args(obj)") void myPointcut(JoinP

我需要创建一个切入点与方法匹配的方面,如果:

  • 它是用MyAnnotationForMethod注释的
  • 它的一个参数(可以有多个)用@MyAnnotationForParam注释(但也可以有其他注释)
  • aspect类如下所示

    @Pointcut("execution(@MyAnnotationForMethod * *(..,@aspects.MyAnnotationForParam Object, ..)) && args(obj)")
    void myPointcut(JoinPoint thisJoinPoint, Object obj) {
    }
    
    @Before("myPointcut(thisJoinPoint ,  obj)")
    public void doStuffOnParam(JoinPoint thisJoinPoint, Object obj) {
        LOGGER.info("doStuffOnParam :"+obj);
    }
    
    注释法

    @MyAnnotationForMethod
    public string theMethod(String a, @MyAnnotationForParam @OtherAnnotation Object obj, Object b){ 
        LOGGER.info(a+obj+b);
    }
    
    使用eclipse->warnings:在poincut上:

    Multiple markers at this line 
        - no match for this type name: MyAnnotationForMethod [Xlint:invalidAbsoluteTypeName] 
        - no match for this type name: aspects.MyAnnotationForParam On the before : advice defined in xxx.xxx.xxx.xxx.MyAspect has not been applied [Xlint:adviceDidNotMatch]
    
    使用来自的最后一个aspectJ插件

    使用aspectj 1.6.9使用maven命令行

    [WARNING] no match for this type name: MyAnnotationForMethod [Xlint:invalidAbsoluteTypeName]
    [WARNING] no match for this type name: aspects.MyAnnotationForParam [Xlint:invalidAbsoluteTypeName]
    [WARNING] advice defined in xxx.xxx.xxx.xxx.MyAspect has not been applied [Xlint:adviceDidNotMatch]
    
    注释:

    package com.xxx.xxx.annotation;
    // standard imports stripped
    @Documented
    @Target( { FIELD, CONSTRUCTOR, PARAMETER })
    @Retention(RUNTIME)
    public @interface @MyAnnotationForParam {}
    

    当然,它不能正常工作

    你能告诉我怎么了吗


    thx.

    更新:

    好的,我能找到的最好的参考资料是在这页:

    您可以匹配方法,但是无法捕获参数(仅捕获方法和注释)。所以你需要做的是切入点匹配和反射的结合。大概是这样的:

    @Pointcut(
        "execution(@com.xxx.xxx.annotation.MyAnnotationForMethod * *(.., @com.xxx.xxx.annotation.MyAnnotationForParam (*), ..))")
    public void annotatedMethod(){}
    
    @Before("annotatedMethod()")
    public void doStuffOnParam(final JoinPoint jp){
        final Signature signature = jp.getSignature();
        if(signature instanceof MethodSignature){
            final MethodSignature ms = (MethodSignature) signature;
    
            final Method method = ms.getMethod();
            final String[] parameterNames = ms.getParameterNames();
            final Class<?>[] parameterTypes = ms.getParameterTypes();
            final Annotation[][] parameterAnnotations =
                method.getParameterAnnotations();
            for(int i = 0; i < parameterAnnotations.length; i++){
                final Annotation[] annotations = parameterAnnotations[i];
                final MyAnnotationForParam paramAnnotation =
                    getAnnotationByType(annotations, MyAnnotationForParam.class);
                if(paramAnnotation != null){
                    this.processParameter(ms.toShortString(),
                        parameterNames[i],
                        parameterTypes[i],
                        paramAnnotation);
                }
    
            }
        }
    }
    
    /**
     * In an array of annotations, find the annotation of the specified type, if any.
     * @return the annotation if available, or null
     */
    @SuppressWarnings("unchecked")
    private static <T extends Annotation> T getAnnotationByType(final Annotation[] annotations,
        final Class<T> clazz){
    
        T result = null;
        for(final Annotation annotation : annotations){
            if(clazz.isAssignableFrom(annotation.getClass())){
                result = (T) annotation;
                break;
            }
        }
        return result;
    }
    
    /**
     * Do some processing based on what we found.
     * @param signature method signature
     * @param paramName parameter name
     * @param paramType parameter type
     * @param paramAnnotation annotation we found
     */
    private void processParameter(final String signature,
        final String paramName,
        final Class<?> paramType,
        final MyAnnotationForParam paramAnnotation){
    
        System.out.println(MessageFormat.format(
            "Found parameter ''{0}'' \n  of type ''{1}'' \n  with annotation ''{2}'' \n  in method ''{3}''",
            paramName,
            paramType,
            paramAnnotation,
            signature));
    }
    
    以下是输出:

    Starting up
    Found parameter 'param1' 
      of type 'class java.lang.String' 
      with annotation '@com.xxx.xxx.annotation.MyAnnotationForParam()' 
      in method 'TestClass.simpleTestMethod(..)'
    Method body (simple)
    Found parameter 'param2' 
      of type 'class java.lang.Float' 
      with annotation '@com.xxx.xxx.annotation.MyAnnotationForParam()' 
      in method 'TestClass.complexTestMethod(..)'
    Found parameter 'param3' 
      of type 'class java.lang.Boolean' 
      with annotation '@com.xxx.xxx.annotation.MyAnnotationForParam()' 
      in method 'TestClass.complexTestMethod(..)'
    Method body (complex)
    Finished
    
    暗示 您可能需要缓存大量的数据,不需要在每次执行中解析每个注释的每个参数。保留带有注释的方法的哪个参数的映射,并仅处理这些参数。

    当从接口实现该方法时,上述解决方案中的ms.getParameterNames()调用似乎不起作用。我得到空值

    但是,如果启用CGLIB,它就会工作

    <aop:aspectj-autoproxy proxy-target-class="true"/>
    
    
    
    您能否显示这两个批注的代码,包括它们的包声明。批注是否具有retention=RUNTIME?相关:Sean,您知道为什么需要自己定义的批注的完整类路径吗。这就是我在过去两个小时里一直在做的事。Thanks@Bill问题是aspectj通常在编译类上工作,而不是在源代码上。导入不存储在类中。因此,实际上没有办法从切入点批注中找到的类名中猜测限定名。@只有@SeanPatrickFloyd使用代理目标类也允许获取参数批注时,Nittin参数名才可用。在添加此设置之前,我总是得到空数组。
    Starting up
    Found parameter 'param1' 
      of type 'class java.lang.String' 
      with annotation '@com.xxx.xxx.annotation.MyAnnotationForParam()' 
      in method 'TestClass.simpleTestMethod(..)'
    Method body (simple)
    Found parameter 'param2' 
      of type 'class java.lang.Float' 
      with annotation '@com.xxx.xxx.annotation.MyAnnotationForParam()' 
      in method 'TestClass.complexTestMethod(..)'
    Found parameter 'param3' 
      of type 'class java.lang.Boolean' 
      with annotation '@com.xxx.xxx.annotation.MyAnnotationForParam()' 
      in method 'TestClass.complexTestMethod(..)'
    Method body (complex)
    Finished
    
    <aop:aspectj-autoproxy proxy-target-class="true"/>