Які scope існують в Spring?
4. Scoped Proxy — для впровадження вузьких scope в широкі 5. ObjectProvider — альтернатива Scoped Proxy 6. RefreshScope — для динамічної конфігурації
🟢 Junior Level
Scope визначає, скільки екземплярів біна створює Spring.
| Scope | Скільки екземплярів |
|---|---|
| Singleton | Один на весь додаток (за замовчуванням) |
| Prototype | Новий при кожному запиті |
| Request | Один на HTTP запит |
| Session | Один на HTTP сесію |
@Service // Singleton
public class UserService { }
@Scope("prototype")
@Service
public class Report { } // Новий щоразу
🟡 Middle Level
Standard Scopes
Singleton:
// Один екземпляр на ApplicationContext
// Усі потоки використовують один об'єкт
→ Повинен бути Stateless!
Prototype:
// Новий при кожному getBean()
// Spring НЕ викликає @PreDestroy!
→ Ви самі чистіть ресурси
Web Scopes
@Scope("request") // Один на HTTP запит
@Scope("session") // Один на сесію користувача
@Scope("application") // Один на ServletContext
Custom Scopes
// Свій scope!
context.getBeanFactory().registerScope("thread", new ThreadScope());
// ThreadScope — кастомна реалізація інтерфейсу org.springframework.beans.factory.config.Scope.
// Зберігає біни в ThreadLocal. У стандартному Spring такий scope не вбудований — це приклад.
// Spring Cloud: Refresh Scope
→ Бін перестворюється при оновленні конфігурації
Проблема: вузький scope в Singleton
// ❌ Request бін створиться один раз під час старту Singleton
@Service
public class SingletonService {
@Autowired RequestBean requestBean; // Застряв перший!
}
// ✅ Scoped Proxy
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
@Bean public RequestBean requestBean() { }
// ✅ ObjectProvider
@Autowired ObjectProvider<RequestBean> provider;
RequestBean bean = provider.getObject(); // Актуальний!
🔴 Senior Level
ScopedProxyMode
TARGET_CLASS (CGLIB):
→ Створює проксі-нащадок
→ Проксі → RequestContextHolder → актуальний бін
INTERFACES (JDK):
→ Проксирує лише інтерфейси
NO:
→ Без проксі → проблема з Singleton
Under the hood: де зберігаються
Singleton → DefaultSingletonBeanRegistry (ConcurrentHashMap)
Request → зберігається в атрибутах HttpServletRequest, доступ через RequestContextHolder (ThreadLocal)
Session → SessionAttributes
Prototype → Не зберігається, створюється щоразу
Refresh Scope (Spring Cloud)
@RefreshScope
@ConfigurationProperties("my.config")
public class MyConfig { }
// При оновленні через Spring Cloud Bus:
// → Проксі інвалідується
// → При наступному запиті створюється заново з новими даними
Production Experience
Реальний сценарій: Session scope в мікросервісі
Session scope → ThreadLocal → працює на одному ноді
→ Load Balancer → запит на інший нод → Session загубився!
Рішення: Spring Session + Redis
→ Session зберігається в Redis → доступний на всіх нодах
Best Practices
- Singleton — для сервісів і репозиторіїв
- Prototype — для важких stateful об’єктів
- Web scopes — для даних користувача
- Scoped Proxy — для впровадження вузьких scope в широкі
- ObjectProvider — альтернатива Scoped Proxy
- RefreshScope — для динамічної конфігурації
Резюме для Senior
- Singleton = один на ApplicationContext
- Prototype = новий щоразу, @PreDestroy НЕ працює
- Request/Session = web scope через ThreadLocal
- Scoped Proxy = проксі → RequestContextHolder
- RefreshScope = перестворення при оновленні конфігурації
- Custom Scope = свій lifecycle
🎯 Шпаргалка для співбесіди
Обов’язково знати:
- 4 стандартних scope: Singleton (за замовчуванням), Prototype, Request, Session
- Singleton = один екземпляр на ApplicationContext, Prototype = новий при кожному запиті
- Web scope (Request/Session) зберігаються через ThreadLocal
- ScopedProxyMode (TARGET_CLASS/CGLIB, INTERFACES/JDK, NO) вирішує проблему впровадження вузьких scope в широкі
- @PreDestroy НЕ викликається для Prototype — ресурси чистіть вручну
- ObjectProvider — альтернатива Scoped Proxy для Prototype/Request в Singleton
- RefreshScope (Spring Cloud) — перестворення біна при оновленні конфігурації
Часті уточнюючі запитання:
- Як впровадити Request scope в Singleton? → Scoped Proxy (
proxyMode = TARGET_CLASS) або ObjectProvider - Що станеться, якщо Prototype бін містить ресурси? → Витік, Spring не викличе @PreDestroy, потрібно чистити вручну через try-finally
- Де Spring зберігає Singleton біни? → DefaultSingletonBeanRegistry (ConcurrentHashMap)
- Що робить RefreshScope? → Інвалідує проксі, при наступному запиті створює бін заново з новими даними
Червоні прапорці (НЕ говорити):
- «Prototype викликає @PreDestroy» — не викликає
- «Request scope зберігається в кеші Spring» — зберігається в атрибутах HttpServletRequest
- «Singleton створюється при кожному зверненні» — створюється один раз
- «Custom Scope вбудований в Spring» — потрібно писати свою реалізацію інтерфейсу Scope
Пов’язані теми:
- [[12. В чому різниця між singleton та prototype scope]]
- [[13. Що таке proxy в Spring]]
- [[14. Коли Spring створює proxy]]
- [[16. Що таке аспект, advice, pointcut, join point]]