Что произойдёт с @Transactional****, если метод объявлен в final-классе
Spring по умолчанию оборачивает бины в CGLIB-прокси — это подкласс вашего класса, который перехватывает вызов и открывает транзакцию до вызова реального метода. Подкласс не может унаследоваться от final-класса.
В Java с обычным классом это ошибка при старте контекста: Spring увидит аннотацию @Transactional, попытается создать прокси-наследника и упадёт на этапе создания бина с понятной ошибкой генерации класса.
С интерфейсными бинами Spring использует JDK-прокси и final на классе не мешает, потому что прокси реализует интерфейс, а не наследует класс. Проблема именно у CGLIB — когда прокси нужен поверх конкретного класса без интерфейса.
@Service public final class PaymentService {
@Transactional public void charge(Long orderId) { // CGLIB не создаст // прокси-наследника } }
Отдельно ловят на final-методе внутри обычного (не final) класса: класс можно унаследовать, а конкретный final-метод — нет, и CGLIB не сможет переопределить именно его. Транзакция тихо не применится, падения при старте не будет — это хуже, чем явная ошибка, потому что баг всплывает только в проде на реальных данных.
Проверка прокси-способности метода и класса — не теоретический вопрос: Kotlin-классы final по умолчанию, и та же ловушка там встречается в разы чаще.
senior·base — что спрашивают на самом деле
В этом посте были ссылки, но мы их удалили по правилам Сетки