Вопрос 14 · Раздел 5

Когда Spring создаёт прокси?

4. Не проксируйте final классы/методы 5. Минимизируйте количество прокси 6. AopUtils → для проверки прокси

Версии по языкам: English Russian Ukrainian

🟢 Junior Level

Spring создаёт прокси, когда видит специальные аннотации:

Аннотация Что добавляет прокси
@Transactional Управление транзакциями
@Async Асинхронное выполнение
@Cacheable Кэширование результатов
@PreAuthorize Проверка прав доступа
@Service
public class MyService {
    
    @Transactional  // ← Прокси для транзакций
    public void save() { }
    
    @Async  // ← Прокси для асинхронности
    public CompletableFuture<Void> process() { }
}

🟡 Middle Level

Функциональные триггеры

@Transactional:

Proxy → открывает транзакцию → вызывает метод → commit/rollback

@Async:

Proxy → передаёт задачу в TaskExecutor → возвращает Future сразу

@Cacheable:

Proxy → проверяет кэш → если есть → возвращает из кэша
     → если нет → вызывает метод → сохраняет в кэш

Scoped Proxies:

@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
// → Прокси ищет актуальный бин в RequestContextHolder

Механизм создания

BeanPostProcessor.postProcessAfterInitialization():
  → AnnotationAwareAspectJAutoProxyCreator сканирует бин
  → Нашёл аннотацию → создаёт прокси
  → Прокси заменяет оригинальный бин в контексте

🔴 Senior Level

AnnotationAwareAspectJAutoProxyCreator

Главный BPP для создания прокси:
  1. Сканирует все аннотации и @Aspect
  2. Для каждого бина проверяет Pointcut
  3. Если подходит → создаёт прокси
  4. Прокси идёт дальше по цепочке BPP

Избежание лишних прокси

Прокси = overhead (память + CPU)
→ Не ставьте @Transactional на методы, которые только читают и не требуют консистентного снимка данных. Если транзакция нужна, используйте `readOnly = true` для оптимизации Hibernate (skip dirty checking).
→ Прокси создаётся на ВЕСЬ бин, даже если одна аннотация

Production Experience

Реальный сценарий: лишний прокси

Каждый прокси — дополнительный объект в памяти и небольшой оверхед на вызов (порядка наносекунд). При большом количестве бинов это суммируется.

Решение: убрали @Transactional с read методов
→ Меньше прокси, меньше overhead

Best Practices

  1. @Transactional → только где нужно
  2. @Async → осторожно, прокси на весь бин
  3. Scoped Proxy → для web scope в Singleton
  4. Не проксируйте final классы/методы
  5. Минимизируйте количество прокси
  6. AopUtils → для проверки прокси

Резюме для Senior

  • Прокси создаётся при @Transactional, @Async, @Cacheable
  • BPP → postProcessAfterInitialization
  • Scoped Proxy → для web scope в Singleton
  • Каждый прокси = память + CPU overhead
  • final → не проксируется
  • AnnotationAwareAspectJAutoProxyCreator → главный создатель

🎯 Шпаргалка для интервью

Обязательно знать:

  • Прокси создаётся при наличии @Transactional, @Async, @Cacheable, @PreAuthorize
  • Механизм: AnnotationAwareAspectJAutoProxyCreator (BeanPostProcessor) в postProcessAfterInitialization()
  • Scoped Proxy (@Scope с proxyMode) — создаёт прокси для web scope в Singleton-бинах
  • Каждый прокси = небольшая память + CPU overhead (наносекунды на вызов)
  • Spring сканирует все аннотации и @Aspect, проверяет Pointcut, создаёт прокси
  • @Transactional на read-методах без необходимости лишний overhead — используйте readOnly = true

Частые уточняющие вопросы:

  • Какой компонент отвечает за создание прокси? → AnnotationAwareAspectJAutoProxyCreator (BPP)
  • Когда создаётся Scoped Proxy? → При @Scope(value="request", proxyMode=TARGET_CLASS)
  • Можно ли избежать создания прокси? → Да, не ставить аннотации где не нужны
  • Как Spring решает, какой тип прокси создать? → proxy-target-class=true → CGLIB, false + есть интерфейс → JDK Proxy

Красные флаги (НЕ говорить):

  • «Прокси создаётся для каждого бина» — только с AOP-аннотациями
  • «@Transactional на read-методах всегда обязателен» — лишний overhead без нужды
  • «Прокси добавляет заметную задержку» — наносекунды
  • «final-классы проксируются через CGLIB» — не проксируются

Связанные темы:

  • [[11. Какие scope существуют в Spring]]
  • [[13. Что такое прокси в Spring]]
  • [[15. Что такое AOP (Aspect-Oriented Programming)]]
  • [[17. Что делает аннотация @Transactional]]