具有注释参数的切入点匹配方法

在以下情况下,我需要使用与方法匹配的切入点创建方面:

  1. 它是用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); } 

注释方法

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

随着eclipse – >警告:关于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] 

使用http://download.eclipse.org/tools/ajdt/35/update中的 last aspectJ插件

使用maven命令行使用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 {} 

当然,它没有正常工作。

你能告诉我有什么问题吗?

谢谢。

更新:

好的,我能找到的最佳参考是在这个页面上: 注释,切入点和建议 。

您可以匹配该方法,但是您将无法捕获参数(只是方法和注释)。 所以你需要做的是切入点匹配和reflection的组合。 像这样的东西:

 @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 getAnnotationByType(final Annotation[] annotations, final Class 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)); } 

这是我上面方面的测试类:

 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 

暗示

您可能希望缓存大量此类内容,无需在每次执行中解析每个注释的每个参数。 保留哪个方法的哪个参数带有注释的地图,并仅处理这些参数。

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

但是,如果我启用CGLIB,那么它可以工作。