Issue
@Component
Class A {
public String methodA() {
return methodB();
}
@Publish
public String methodB() {
return "abc";
}
}
@Component
@Aspect
public class PublishEvents {
@AfterReturning(value = "@annotation(Publish)", returning = "retVal")
public void sendEvent(JoinPoint joinPoint, Object retVal) {
system.out.println("sending event");
}
}
So I have an aspect class PublishEvents
defined with AfterReturning
Advice. This advice gets executed when I use @Publish
which is a custom defined annotation, over methodA
of class A but it does not get executed when I put it over methodB
of class A. Note that methodB
is called from methodA
.
Can someone tell me what I am missing here?
Solution
Spring AOP is proxy-based, which means that an additional class for proxying bean calls is created by Spring, for more details about proxy mechanisms check the link.
The key thing to understand is that calls on that component reference are calls on the proxy. To make it more clear, other beans, that autowire the A
component, actually contain the proxied instance, not the component instance itself. As a result, the proxy can delegate to all the interceptors (advice) relevant to that particular method call.
However, any method calls it may make on itself, such as methodA
invoking methodB
in your case, will be invoked against the instance itself, not the proxy. This has important implications. It means that self-invocation will not result in the AfterReturning
advice getting a chance to run.
Unlike Spring AOP, AspectJ has no issues with self-invocation since it's not a proxy-based AOP framework. Check Indra's answer for more details and examples.
For reference: Understanding AOP Proxies
Answered By - birca123
Answer Checked By - Clifford M. (JavaFixing Volunteer)