If I have Annotation:
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Loggable {
enum LogLevel {
ERROR, WARN, INFO, DEBUG, TRACE;
}
LogLevel value() default DEBUG;
}
and trying to use it as target marker of Spring AOP aspect joinpoint marker, it works well for some aspect, weaved by that composite pointcut:
@Aspect
class LoggableAspect {
@Pointcut("within(@Loggable *)")
void aClass() {}
//@Pointcut("@annotation(Loggable)") - in straight-forward case it works too!
@Pointcut("execution(@Loggable * *(..))")
void method() {}
@Around("method() || aClass()")
Object aroundAdvice(ProceedingJoinPoint pjp) {...}
}
In other words, it works well as "straight-forward" annotation usage, when I write code like this:
@Component
public class Abc {
@Loggable
public String method(int x) {
return "string: " + x;
}
}
But in case of META-annotation...:
@Loggable(INFO)
@Retention(RUNTIME)
public @interface Log {
}
...it doesn't work for example, in that code:
@Component
public class Abc {
@Log // doesn't work! :(
public String method(int x) {
return "string: " + x;
}
}
Certainly, I can write yet another pointcut for that particular case of 2-level deepness:
//...
@Pointcut("execution(@(@Loggable *) * *(..))")
void metaMethod() {}
@Around("method() || metaMethod() || aClass()")
Object aroundAdvice(ProceedingJoinPoint pjp) {...}
and it will work, but I want universal solution, working on any level of deepness - 3, 4, 5... Is it possible for that style of AOP?
P.S. That issue:
execution(public * ((@Transactional *)+).*(..))
looks like exactly right solution, but unfortunately, it doesn't work in my case. I think, it's possible only as AspectJ solution (in *.aj files) - not for Spring AOP. Am I right?..