Why @Transactional on private methods usually fails and how AspectJ makes it work

The article explains that Spring's @Transactional annotation does not affect private methods because transactions are applied via proxy objects, but using AspectJ weaving or programmatic TransactionTemplate can overcome this limitation and ensure proper transaction handling.

samdeepthink
samdeepthink
samdeepthink
Why @Transactional on private methods usually fails and how AspectJ makes it work

If you answer in an interview that @Transactional on a private method never works, you lose points; you need to know that by default it doesn’t work, but it can be enabled with AspectJ weaving.

@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)

With AspectJ, Spring modifies bytecode at compile‑time or load‑time, weaving transaction logic directly into the method, so even private methods receive transaction handling.

Common misconceptions:

Java does allow @Transactional on private methods; the @Target includes METHOD and does not restrict visibility.

Spring’s annotation processing is not buggy; the same annotation works on public methods.

The database is irrelevant; it does not know Java method visibility.

Spring actually creates a proxy object to wrap the original bean. When external code calls a method, it interacts with the proxy, which contains a TransactionInterceptor. The interceptor checks for transaction metadata, starts a transaction via the transaction manager, executes the business logic, and commits or rolls back based on exceptions. Therefore, a transaction only works if the call goes through the proxy.

Because Spring uses CGLIB to generate the proxy subclass, and Java forbids overriding private methods in subclasses, private methods are never overridden and thus never intercepted.

Even a public method annotated with @Transactional can fail if it is invoked internally from the same class (self‑invocation). The internal call uses this, bypassing the proxy, so the transaction is not applied—exactly the same root cause as with private methods.

Avoid @Transactional; use TransactionTemplate instead

In practice, the author’s team prefers programmatic transactions with TransactionTemplate, which does not rely on AOP proxies and gives explicit control over transaction boundaries.

transactionTemplate.execute(status -> {
    orderMapper.insert(order);
    orderItemMapper.batchInsert(order.getItems());
    return null;
});

This approach prevents accidental expansion of transaction scope, which can happen with declarative @Transactional when additional remote calls or heavy queries are added, leading to long‑running transactions and connection‑pool exhaustion under high concurrency.

Key takeaways for interviews:

By default, @Transactional works only when the method call passes through a Spring proxy.

Private methods are not proxied because CGLIB cannot override them.

Self‑invocation of public @Transactional methods suffers the same proxy‑bypass issue.

AspectJ weaving or programmatic TransactionTemplate can solve these problems.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaSpringAspectJTransaction ManagementCGLIBTransactionTemplate
samdeepthink
Written by

samdeepthink

Knowledge Planet: Old Dock's Tech Chronicles Zhihu: SamDeepThinking A technical manager who still codes heavily on the front line. From junior developer to tech lead, then tech manager, now leading the whole front‑ and back‑end development team—leveling up along the way. I have some insights on programming, career development, and tech management.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.