The self-calling limitation in Spring-AOP and one unintrusive solution
May 29, 2007 – 19:45 | aop, java, springSpring-AOP is implemented by creating proxies decorating the target bean. One typical gotcha from using these proxies, for instance, in declarative transaction management, is the proxy can't intercept a call made from one method to another on the same target object (typically a service bean), even though both methods are supposed to be wrapped by the proxy.
One obvious solution to the problem is to always explicitly get the bean reference from the Spring context and then call the method on it, instead of calling the method on 'this'. For example, instead of this.anotherServiceMethod(), do:
-
// get hold of the application context either through
-
// a singleton locator or through a private reference, then
-
context.getBean("aServiceBean").anotherServiceMethod();
It's an easy solution, but one that doesn't come without a few nuisances. For instance, it adds to your service bean some compile-time dependencies on Spring classes that wouldn't have been necessary otherwise.
One less intrusive solution I've come up with is a AdviceSkippingInjector.java that injects the reference to any proxied Spring bean into a property on the "raw" bean, i.e., the object prior to being wrapped in the proxy.
To use it, add a proxiedSelf property to the service bean (it doesn't have to be on any public interface), add this to your context file:
-
<bean id="aService" class="your.proxied.service.Bean">
-
</bean>
-
-
<bean id="ProxySkippingInjector" class="com.digizen.commons.spring.AdviceSkippingInjector">
-
<property name="beanProperties">
-
<map>
-
<entry key="aService" value="proxiedSelf" />
-
</map>
-
</property>
-
</bean>
In the map beanProperties, each key is a bean name defined in the context, and the corresponding value a property name on the bean. At run-time, if the AdviceSkippingInjector sees a bean name in its map, it will drill into the proxies, find the reference to the original bean, and inject the reference to the proxy into the original bean's proxiedSelf property.
This solution is unintrusive because the service bean remains unaware of any of the plumbing work. All the wiring is done in the application context. In fact, the service bean isn't even necessarily aware that proxiedSelf, despite the name, points to its "proxied self".

3 Responses to “The self-calling limitation in Spring-AOP and one unintrusive solution”
Many many thanks...
I was trying to call one transactional function from another. But the called transactional method was not running in a transaction, bacause the invocation was going through the 'this' pointer not through the automatically created proxy. I was aware of the problem, but was not able to work around this. Your AdviceSkippingInjector.java hit at the bull's eye. It solved the problem which I was trying for 2 days.
By Pradeep Kumar on Sep 16, 2009
Excellent solution
By Ramesh on Mar 10, 2010
Hey Jing!
Thanks! After some tinkering which was caused by some
careless configuration your solution seems to work like a charm!
A bit of code on the service class to help some needy soul..
The service class (implemenation of PersonDAO interface)
public class SimplePersonManager implements PersonManager
{
private PersonDAO personDAO;
private PersonManager proxiedSelf;
public void setProxiedSelf(PersonManager proxSelf)
{
this.proxiedSelf = proxSelf;
}
Thanks again and keep up the great work!
By Duminda on Nov 10, 2010