I have an annotation which can be placed on a class or a method:
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.TYPE}) public @interface TestAspectAnnotation { String[] tags() default {}; } I want to have a single advising method to handle both class-level and method-level usages:
@Around(value = "@annotation(annotation) || @within(annotation)", argNames = "pjp,annotation") public Object testAdvice(ProceedingJoinPoint pjp, TestAspectAnnotation annotation) throws Throwable { String[] tags = annotation.tags(); Stopwatch stopwatch = Stopwatch.createStarted(); Object proceed = pjp.proceed(); stopwatch.stop(); long executionTime = stopwatch.elapsed(TimeUnit.MILLISECONDS); sendMetrics(tags, executionTime); return proceed; } This works fine when I annotate a class with TestAspectAnnotation(tags="foo").
However, if I annotate a method, annotation argument will be null.
Interestingly, if I reverse the order of the pointcut designators ("@within(annotation) || @annotation(annotation)"), then I will have the reverse problem: method-level annotations will work fine, but class-level annotations will result in null for for the annotation argument.
Is there a way have a single pointcut and advice to support the annotation at both a class-level and method-level?