Edit:
You need to understand how Spring proxying works in order to understand why your refactoring does not work.
A method call by reference to an object will be a proxy server call, and thus the proxy server will be able to delegate to all interceptors (tips) that are relevant to this particular method call. However, as soon as the call finally reaches the target, any method call that it can make on its own will be called against this link, not the proxy. This has important implications. This means that self-exclusion will not cause the advice associated with the method call to be able to execute.
@Transactional uses Spring AOP, Spring uses a proxy. This means that when you call the @Transactional method from another class, Spring will use a proxy server, so transaction advice will be applied. However, if you call a method from the same class, Spring will use the "this" link instead of the proxy, so transaction recommendations will not apply.
Original answer:
Here's what worked for me in a similar scenario.
public class DoStuff implement ApplicationContextAware { private ApplicationContext CONTEXT; public void setApplicationContext(ApplicationContext context) throws BeansException { CONTEXT = context; } public void originalMethod() { getSpringProxy().doDatabaseStuff() doNonDatabaseStuff() } private DoStuff getSpringProxy() { return context.getBean(this.getClass()); } @Transactional public void doDatabaseStuff() { ... } public void doNonDatabaseStuff() { ... } }
Explanation:
- Make the
ApplicationContextAware class, so it has a context reference - When you need to call a transaction method, select the actual Spring proxy from the context
- Use this proxy to call your method so that @Transactional actually applies.
source share