Spring / Spring7 Intermediate to Advanced Interview questions
Why doesn't @Transactional work when called from within the same class (self-invocation)?
Spring's default @Transactional support is implemented with AOP proxies - a JDK dynamic proxy if the target implements an interface, or a CGLIB-generated subclass otherwise. The transactional behavior (starting, committing, rolling back) is advice woven in at the proxy layer, not inside the target class's own bytecode.
@Service public class OrderService { public void placeOrder(Order order) { // called via "this." - bypasses the proxy entirely this.saveOrder(order); } @Transactional public void saveOrder(Order order) { /* ... */ } }
When placeOrder calls this.saveOrder(order), that's a plain Java virtual method call on the raw target object - the call never goes back out through the proxy that Spring registered in the container, so none of the transactional interceptor logic runs. saveOrder executes with no transaction at all, silently, which is what makes this bug particularly hard to catch in testing.
Common fixes: split the transactional method into a separate collaborator bean and inject it, so the call genuinely goes through a proxy; inject the bean's own proxy back into itself (via @Lazy self-autowiring or ApplicationContext.getBean(...)) and call through that reference; or switch to AspectJ compile-time or load-time weaving, which instruments the actual bytecode rather than relying on a wrapper proxy, so self-invocation is advised correctly.
More Related questions...