DaveH DaveH - 3 months ago 12
Java Question

Get the name of a concrete class within aspectJ advice

I am attempting to use aspectJ to intercept calls to public methods on classes which implement my

Loggable
interface. Loggable is a marker interface and defines no methods.

I have a
before
advice, in which I want to get the name of the Concrete class containing the method that is being called. By using
thisJoinPoint.getTarget()
I can get the concrete class, but when I call
thisJoinPoint.getTarget().getClass.getName()
I get a stackoverflow exception.

I'm pretty sure that this is because I am calling a public method on the Concrete class, which then causes my
before
advice to re-fire.

Here's my pointcut :

pointcut dave() : target(Loggable) && call (public * *(..) ) ;


How do I limit this to only the public methods that are defined directly within the concrete class, ignoring those that are inherited from java.lang.Object?

Answer

While StackOverflow is not an opinion-based discussion forum, I am going to answer with a few concrete examples in order to be a bit more explicit:

If !this(LoggerAspect) works for you, use it. But beware: It will not keep the advice from firing when a call() is indirectly, i.e. a method called by your advice, calling another method.

Option 1: use execution() instead of call()

When using an execution() pointcut, AspectJ fires only when the callee is executed, i.e. in one single place, not in many places where your callee is called by the caller. This is more efficient and in this context whould work for you because you seem to control the called code. Only if the aspect weaver/compiler does do have access to the callee, you should weave the caller using a call() pointcut.

As a side effect, executions of 3rd party library or JDK code will not be intercepted by execution() anyway because it is not accessible to the compiler/weaver with one exception being 3rd party libs (but not JDK code) woven via LTW (load-time weaving).

Option 2: adviceexecution() pointcut

By combining your pointcut with && !adviceexecution() you can stop the advice from firing when a call() is made while any advice in any of your aspects is being executed. This also excludes indirect calls and works nicely for a single advice. But if you combine multiple aspects and want your advice to still fire when a call() is made by another aspect's advice, you probably want to use another option such as...

Option 3: within() pointcut

By combining your pointcut with && !within(LoggerAspect) you can stop the advice from firing when a call() is made from within any advice in your LoggerAspect. Calls from other aspects are still being logged.

What exactly you want to achieve determines which option (or combination thereof) you should choose. There is no simple answer because I do not know your exact situation.

Comments