This forum is now a read-only archive. All commenting, posting, registration services have been turned off. Those needing community support and/or wanting to ask questions should refer to the Tag/Forum map, and to http://spring.io/questions for a curated list of stackoverflow tags that Pivotal engineers, and the community, monitor.

self invocation in intercepted object

Aug 1st, 2009, 01:08 PM

Current Spring proxy has one problem, when a method being invoked from another method from the same class instance, it will bypass the whole interceptor stack. For example, there is a method 1 with @Transactional annotation, andanother method 2 in the same class without @Transactional annotation, but it is calling method 1. An external user calling method 1 will be intercepted by transaction logic; however, calling to method 2 will not have transaction enforced, even we think it should be.

There is one solution to inject proxy of itself to the instance, any method needs to calling another method in the same class must use the proxy "me" rather than direct call. To me, it is more a not so elegant workaround because programmers have to aware of the fact that proxy is no longer transparent to them, and calling method of another service will have different behavior than calling method of itself.

I personally do not like the workaround, so I developed some code to use CGLIB to generate a subclass of the target class with methods intercepted, rather than creating a proxy delegate to the target instance. Here's how I have it done.
1. In current implementation I only intercepted methods with certain annotations;
2. I have a list of annotation type and its interceptors;
3. I replaced the default instantiate strategy with my implementation, so it checks a bean class to see if it is annotated by any special annotation types, if so, a CGLIB enabled subclass instance will be generated, with annotated methods being intercepted.

So when a method calls to another method of the same class, because the bean instance is already a CGLIB subclass, that target method is intercepted anyway.

This solution has its limitation, for example, the class can not be final and the annotated method can not be final. I know it would be showstopper for some developers, I am fine with that limitation, it is just something like do not make it final when you want it to be intercepted. It makes sense to me.