Spring, by default, uses runtime weaving (unlike AspectJ – see this) for aspects. In runtime weaving, a proxy class is generated for your “adviced” classes and they are decorated with the advices at runtime. @Transaction annotation works the same way. In default mode, annotated transactional beans are processed to be proxied using Spring’s AOP Framework. This means that for a method to be transactional, it needs to be invoked from outside the class it is defined in. Request should come from outside and so go through the proxy class (see the quotes below).
Another thing is that it is recommended to annotate the concrete classes with @Transactional annotation, not the interfaces. It will work only if you use interface-based proxies.
The Spring team recommends that you annotate only concrete classes (and methods of concrete classes) with the
@Transactionalannotation, as opposed to annotating interfaces. You certainly can place the
@Transactionalannotation on an interface (or an interface method), but this works only as you would expect it to if you use interface-based proxies. The fact that Java annotations are not inherited from interfaces means that, if you use class-based proxies (
proxy-target-class="true") or the weaving-based aspect (
mode="aspectj"), the transaction settings are not recognized by the proxying and weaving infrastructure, and the object is not wrapped in a transactional proxy, which would be decidedly bad. (ref)
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation (in effect, a method within the target object calling another method of the target object) does not lead to an actual transaction at runtime even if the invoked method is marked with
@Transactional. Also, the proxy must be fully initialized to provide the expected behavior, so you should not rely on this feature in your initialization code (that is,
Consider using of AspectJ mode (see the
modeattribute in the following table) if you expect self-invocations to be wrapped with transactions as well. In this case, there no proxy in the first place. Instead, the target class is woven (that is, its byte code is modified) to turn
@Transactionalinto runtime behavior on any kind of method. (ref)
JDK Dynamic Proxy vs CGLIB Proxy
JDK Dynamic proxy can only proxy by interface. In this scenario, so your target class needs to implement an interface, which is then also implemented by the proxy class. CGLIB can create a proxy by subclassing. In this scenario, the proxy becomes a subclass of the target class. No need for interfaces. Note that CGLib (Code Generation Library) is a 3rd party library.
So Java Dynamic proxies can proxy: public class Foo implements iFoo where CGLIB can proxy: public class Foo. (related)
“proxy-target-class” attribute for annotation-driven transaction settings
Applies to proxy mode only. Controls what type of transactional proxies are created for classes annotated with the @Transactional annotation. If the proxy-target-class attribute is set to true, class-based proxies are created (CGLIB). If proxy-target-class is false or if the attribute is omitted, then standard JDK interface-based proxies (JDK Dynamic Proxy) are created.
Hope this helps.