From Does Spring @Transactional attribute work on a private method?
When using proxies, you should apply the @Transactional annotation only to metho
Additional info to the other answers.
Here is an example picture from the Spring blog:
As you can see the proxy is wrapped around the implementing class (here the AccountServiceImpl
) and the proxy itself implements only methods from the AccountService
interface. An Interface
provides only public methods (public contract), so a proxy can not be wrapped around the protected method and provide the transactional behavior, which it provides on public methods.
Calling methods in the same service is possible, if you would use AspectJ
, but I'm not sure if this also counts for protected
methods, because I haven`t used it until now.
Protected methods are not part of the public contract. That's why they are not proxied. They are not visible to the consumer in most cases.
You could call protected methods if you a) wire by IF and cast down to the concrete implementation (bad) or b) wire the concrete implementation and the consumer resides in the same package. As only b) makes sense, I can see why Spring does not proxy protected methods. It's a rare corner case and would only work with CGLIB, not JDK proxies.
Maybe you wonder about the use case of extending a bean and calling super.myProtectedMethod()
: those calls are not proxied at all, independent of access level.
Because of this:
In proxy mode (which is the default), only 'external' method calls coming in through the proxy will be intercepted. This means that 'self-invocation', i.e. a method within the target object calling some other method of the target object, won't lead to an actual transaction at runtime even if the invoked method is marked with @Transactional!
And this:
Due to the proxy-based nature of Spring's AOP framework, protected methods are by definition not intercepted, neither for JDK proxies (where this isn't applicable) nor for CGLIB proxies (where this is technically possible but not recommendable for AOP purposes). As a consequence, any given pointcut will be matched against public methods only!
The Spring guys would probably want to keep consistency with JDK proxies. You wouldn't want to have different proxy configuration and different results based on JDK versus CGLIB.