Що означає "lifetime" залежностей (singleton, scoped, transient)?
"Lifetime залежностей" (час життя залежностей) - це поняття із систем Dependency Injection, яке визначає:
як довго об'єкт, створений контейнером залежностей, буде існувати і коли він буде перестворюватися.
Іншими словами, lifetime керує життєвим циклом екземплярів залежностей у застосунку.
Основні типи lifetime
1. Singleton (один на весь застосунок)
Контейнер створює один екземпляр об'єкта і використовує його всюди, де потрібна ця залежність.
@Singleton
class ConfigService { ... }Як працює:
- створюється один раз при запуску застосунку,
- використовується всіма компонентами,
- знищується при завершенні роботи програми.
Підходить для:
- конфігурацій, логерів, кешування, константних сервісів.
Не підходить для:
- компонентів, що залежать від даних користувача, запиту чи стану.
Ідея: "один на всіх і назавжди".
2. Scoped (один на контекст, наприклад, запит/сесію)
Контейнер створює новий екземпляр для кожного "контексту", наприклад HTTP-запиту, користувацької сесії чи транзакції.
services.AddScoped<IUserService, UserService>();Як працює:
- всередині одного контексту використовується один і той самий об'єкт,
- при новому запиті контейнер створює новий екземпляр.
Підходить для:
- роботи з даними запиту, транзакціями, контекстами БД.
Не підходить для:
- глобальних сервісів, які повинні бути спільними для всіх.
Ідея: "один об'єкт на один запит".
3. Transient (новий при кожному використанні)
Контейнер створює новий екземпляр залежності щоразу, коли вона запитується.
services.AddTransient<IFormatter, HtmlFormatter>();Як працює:
- кожен запит до контейнера - новий об'єкт,
- немає кешування, немає повторного використання.
Підходить для:
- легких, короткоживучих об'єктів,
- утиліт, форматерів, обробників подій.
Не підходить для:
- важких чи повільних компонентів, які часто створюються.
Ідея: "щоразу - чистий екземпляр".
Приклад для наочності (C# / .NET)
services.AddSingleton<Logger>();
services.AddScoped<UserRepository>();
services.AddTransient<NotificationService>();Як це працює:
| Компонент | Створюється | Скільки живе |
|---|---|---|
| Logger | один раз при запуску | весь час |
| UserRepository | один раз на HTTP-запит | до кінця запиту |
| NotificationService | новий щоразу | лише поки використовується |
Чому це важливо
Неправильне управління lifetime може призвести до:
- витоків пам'яті (якщо scoped-об'єкт "приклеївся" до singleton),
- розсинхронізації даних (якщо singleton зберігає змінюваний стан),
- випадкових конфліктів (якщо transient-об'єкти створюються занадто часто).
Висновок:
Lifetime - це "термін життя" залежностей у контейнері DI. Він визначає, коли створюється об'єкт, скільки живе і хто ним володіє.
- Singleton - один на весь застосунок.
- Scoped - один на контекст (наприклад, запит).
- Transient - щоразу новий.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.