切入点匹配的方法与参数注解 [英] Pointcut matching methods with annotated parameters

查看:309
本文介绍了切入点匹配的方法与参数注解的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to create an aspect with a pointcut matching a method if:


  1. 这是annoted与MyAnnotationForMethod

  2. 它的一个参数(可以有多个)都标注有@MyAnnotationForParam(但可以有其他的注释也一样)。

纵横类看起来像这样

@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);
}

该annoted方法

The annoted method

@MyAnnotationForMethod
public string theMethod(String a, @MyAnnotationForParam @OtherAnnotation Object obj, Object b){ 
    LOGGER.info(a+obj+b);
}

在Eclipse - >警告:在poincut:

With eclipse -> warnings : On the 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插件href=\"http://download.eclipse.org/tools/ajdt/35/update\">http://download.eclipse.org/tools/ajdt/35/update

通过使用AspectJ 1.6.9的Maven命令行

With maven command line using aspectj 1.6.9

[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 {}

package com.xxx.xxx.annotation;
// standard imports stripped
@Target(METHOD)
@Retention(RUNTIME)
@Documented
public @interface MyAnnotationForMethod {}

当然,它不正常工作。

And of course it doesn' work properly.

你能告诉我什么是错?

THX。

推荐答案

更新:

OK,我能找到的最好的参考就是这个页面上:<一href=\"http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations-pointcuts-and-advice.html#package-and-parameter-annotations\">Annotations,切入点和通知。

OK, the best reference I could find is on this page: Annotations, Pointcuts and Advice.

您可以匹配的方法,但是你将无法赶上参数(只是方法和注释)。所以,你必须做的是切入点的匹配和反射的组合。事情是这样的:

You can match the method, however you won't be able to catch the parameter (just the method and the annotation). So what you will have to do is a combination of pointcut matching and reflection. Something like this:

@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));
}

下面是我的测试类的上述方面:

Here is my test class for the above aspect:

public class TestClass{

    @MyAnnotationForMethod
    public void simpleTestMethod(@MyAnnotationForParam final String param1){
        System.out.println("Method body (simple)");
    };

    @MyAnnotationForMethod
    public void complexTestMethod(final String param1,
        @MyAnnotationForParam final Float param2,
        @MyAnnotationForParam final Boolean param3){
        System.out.println("Method body (complex)");
    };

    public static void main(final String[] args){
        System.out.println("Starting up");
        final TestClass testObject = new TestClass();
        testObject.simpleTestMethod("Hey");
        testObject.complexTestMethod("Hey", 123.4f, false);
        System.out.println("Finished");
    }

}

和这里是输出:

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

提示

您可能会想缓存很多这一点,就没有必要解析每个标注的各项参数在每次执行。保持一个地图,其中的参数的方法进行注释和处理仅是那些参数。

Hint

You will probably want to cache a lot of this, there is no need to parse every parameter of every annotation in every execution. Keep a map of which parameter of which method carries the annotation and process only those parameters.

这篇关于切入点匹配的方法与参数注解的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆