Карта / Spring AOP / Как работают прокси

Как работают прокси

Spring реализует AOP через Proxy (см. тему «Структурные (Adapter, Proxy)») — оборачивает твой бин в объект-обёртку, который перехватывает вызовы методов и добавляет сквозную логику до/после реального вызова.

@Service
class UserService {
    @Transactional
    void createUser(User user) { ... }
}

// то, что реально внедряется в другие классы — НЕ UserService напрямую,
// а прокси вокруг него:
class UserService$$SpringCGLIB$$Proxy extends UserService {
    void createUser(User user) {
        // открыть транзакцию
        super.createUser(user);   // вызов реального метода
        // закоммитить/откатить транзакцию
    }
}

(Класс прокси показан упрощённо для понимания — реальное имя генерируется Spring динамически.)

Копнуть глубже

Два способа создания прокси в Spring:

  • JDK Dynamic Proxy — если бин реализует интерфейс, Spring создаёт прокси на основе этого интерфейса;
  • CGLIB — если бин не реализует интерфейс (просто обычный класс), Spring создаёт прокси через наследование от самого класса (поэтому такой класс не может быть final, иначе унаследоваться невозможно).

Главное практическое следствие — вызов “изнутри себя” не проходит через прокси. Когда метод одного класса вызывает другой метод того же класса напрямую (this.otherMethod()), это обычный Java-вызов, минующий прокси-обёртку — поэтому @Transactional/@Cacheable/любая AOP-логика на otherMethod() не сработает в этом случае:

@Service
class UserService {
    void outerMethod() {
        this.innerMethod();   // вызов МИМО прокси — @Transactional не сработает!
    }
    @Transactional
    void innerMethod() { ... }
}

Решение — вызывать через другой бин (внедрить self-инъекцию или вынести innerMethod в отдельный сервис), чтобы вызов реально прошёл через прокси-объект, а не напрямую внутри класса.

🎤 Закрыл тему, если можешь объяснить:
• идею Proxy в основе Spring AOP — оборачивание бина;
• почему вызов метода "изнутри себя" не проходит через прокси и как это обойти (если дошёл до 3-го слоя).