PDA

View Full Version : AOP, Proxies, and method calling in same instance


adepue
Aug 26th, 2004, 02:21 PM
Spring can use JDK's Proxy mechanism to apply AOP. However, is it not true that an object instance that has an aspect applied by JDK's Proxy mechanism bypasses the aspect when it invokes its own methods? In other words, when an outside class invokes my proxied class, it will have the benefit of the aspect. But, if the proxied instance invokes another method on itself, then the aspect will not be applied on the method call. I should probably test this before posting, but I strongly suspect it is true. If true, this should be well documented as it can lead to difficult bugs.

irbouho
Aug 26th, 2004, 03:54 PM
Spring does not use bytecode instrumentation to implement AOP. So it is predictable that if a method of a proxied object calls an other method in the same object, the aspect will not be applied on the method call.
Spring allows however to apply the aspect on this method call by setting exposeProxy to True and using AopContext.currentProxy().

//inside method1
((MyBean) AopContext.currentProxy()).method2();


I find this approch a little intrusive.

Laurent PETIT
Jun 22nd, 2005, 07:37 AM
Spring does not use bytecode instrumentation to implement AOP. So it is predictable that if a method of a proxied object calls an other method in the same object, the aspect will not be applied on the method call.
Spring allows however to apply the aspect on this method call by setting exposeProxy to True and using AopContext.currentProxy().

//inside method1
((MyBean) AopContext.currentProxy()).method2();


I find this approch a little intrusive.

Hello,

Yeah, "a little" is quite an Euphemism, isn't it ? :-)

I think this problem could be "partially" solved with the use of CLIB instead of Dynamic Proxies : since the target class will be subclassed, calls to this() will first cause the overriden method to execute, thus allowing the AOP mechanism to work.

Of course there will still be some problems here with CGLib, since all the methods marked as "final" cannot be subclassed

Do I have the point ? Or did I miss something ?

Andreas Senft
Jun 22nd, 2005, 08:38 AM
An alternative solution could be the following:

Introduce a "this" property (with getter and setter) and invoke methods on the same instance via the getter. So getThis().foo() instead of this.foo().

The backing property is by default "this" but might be overriden with the proxy (if the instance is being proxied). If the proxy instance is being injected, no call to AOP specific methods is required.

This approach is still a bit intrusive but works with and without a proxy being present.

Regards,
Andreas

oliverhutchison
Jun 22nd, 2005, 06:46 PM
I think this problem could be "partially" solved with the use of CLIB instead of Dynamic Proxies : since the target class will be subclassed, calls to this() will first cause the overriden method to execute, thus allowing the AOP mechanism to work.

Unfortunately this is not possible. CGLIB proxies must delegate to the target object as it's not possible to add behaviour to an existing object. e.g.

class AdvisedFoo extends Foo {
Foo target;

void fooBar() {
// do before advice
// do around advice
target.fooBar();
// do after advice
}
}

As you can see CGLIB is really no help at all and Andreas solution is looking pretty nice.

Ollie

wpoitras
Jun 22nd, 2005, 07:00 PM
Could you use a combination of BeanNameAware and BeanFactoryAware interfaces to retrieve a reference to itself?

Andreas Senft
Jun 23rd, 2005, 03:42 AM
Could you use a combination of BeanNameAware and BeanFactoryAware interfaces to retrieve a reference to itself?

I think so. But then you are bound to Spring (and I think that's to be avoided).

Regards,
Andreas

Laurent PETIT
Jun 23rd, 2005, 05:04 PM
I think this problem could be "partially" solved with the use of CLIB instead of Dynamic Proxies : since the target class will be subclassed, calls to this() will first cause the overriden method to execute, thus allowing the AOP mechanism to work.
Unfortunately this is not possible. CGLIB proxies must delegate to the target object as it's not possible to add behaviour to an existing object. e.g.

...

As you can see CGLIB is really no help at all and Andreas solution is looking pretty nice.

Ollie
Since I still haven't done this myself, I now doubt that you're right.
Please refer to this thread : http://forum.springframework.org/showthread.php?t=13587]Metod Advice + inner object method invokes Question where it is said that, apparently, this is possible.

So I think someone doesn't correctly interpret the way CGLib works.
Mmmm ... think I will try it myself to be sure ;-p[/url]

oliverhutchison
Jun 23rd, 2005, 07:16 PM
So I think someone doesn't correctly interpret the way CGLib works

Laurent,

it's quite simple. Using the standard Java APIs you can not dynamically add behaviour to an existing object instance or, for that matter, any loaded class.

If you take the time to *think* this through and you will see that I must be correct.

Ollie

latham
Jul 16th, 2005, 07:54 AM
Spring can use JDK's Proxy mechanism to apply AOP. However, is it not true that an object instance that has an aspect applied by JDK's Proxy mechanism bypasses the aspect when it invokes its own methods? In other words, when an outside class invokes my proxied class, it will have the benefit of the aspect. But, if the proxied instance invokes another method on itself, then the aspect will not be applied on the method call. I should probably test this before posting, but I strongly suspect it is true. If true, this should be well documented as it can lead to difficult bugs.

So it is true, and should be documented. Today I've found a bug in my code that was caused by this behaviour.

chhajed
Jul 29th, 2005, 03:50 AM
please refer to the proposed solution for more info

http://forum.springframework.org/showthread.php?t=16896

Thanks,
Amit Chhajed

hay7777
Feb 1st, 2006, 07:42 AM
this link doesn't work!!