@Transactional-сервисов в Spring BootКогда вы используете
@Transactional на методе сервиса, Spring оборачивает бин в прокси. Но если вы решите сделать ленивую инициализацию (@Lazy) или внедрите такой бин в другой с помощью ObjectProvider.getIfAvailable() или @Autowired(required = false) — есть риск неожиданного поведения.📌 Типичный баг:
@Service
@Lazy
public class MyService {
@Transactional
public void doSomething() {
// ...
}
}
🔍 Если где-то в коде вызвать
applicationContext.getBean(MyService.class) в момент, когда прокси ещё не создан — вы получите оригинальный, не-прокси-объект. А значит, @Transactional не сработает.⚠️ В результате — метод выполнится без транзакции, и вы не поймёте почему.
💡 Как избежать:
* Никогда не используйте
@Lazy или ленивое получение @Transactional-сервисов, если не понимаете нюансов проксирования.* Лучше разделите логику: сервис без прокси — отдельно, бизнес-методы с
@Transactional — в другом бине.✅ Надёжный способ: вызывать
@Transactional-методы только через Spring-контейнер. Даже внутри самого сервиса — через self-injection:
@Service
public class MyService {
private final MyService self;
public MyService(@Lazy MyService self) {
this.self = self;
}
public void doWrapper() {
self.doTransactional(); // прокси работает
}
@Transactional
public void doTransactional() {
// ...
}
}
👉 @java_geek