docs/references/lifecycle/README.md
This is the main entry point for Cherry Studio's service lifecycle and application orchestration documentation. The lifecycle system provides IoC container management, phased bootstrap, and service lifecycle control.
| Lifecycle | Direct-import singleton | |
|---|---|---|
| Examples | DbService, CacheService, MainWindowService | ExportService, BackupManager, OcrService |
| Long-lived resources | Yes | No (or request-scoped) |
| Persistent side effects | Yes | No |
onInit / onStop | Meaningful | Would be empty |
| Pattern | @Injectable + application.get() | export const x = new X() |
┌───────────────────────────────────┐
│ Owns long-lived resources? │
│ (connections, timers, native │
│ modules, servers, processes) │
└─────┬────────────────┬────────────┘
yes │ │ no
▼ ▼
┌───────────┐ ┌──────────────────────────┐
│ Lifecycle │ │ Registers persistent │
└───────────┘ │ side effects? │
│ (listeners, shortcuts, │
│ subscriptions, etc.) │
└─────┬───────────┬────────┘
yes │ │ no
▼ ▼
┌───────────┐ ┌────────────────┐
│ Lifecycle │ │ Direct-import │
└───────────┘ │ singleton │
└────────────────┘
For the full decision framework with examples, condition tables, and common mistakes, see Lifecycle Decision Guide.
WhenReady services do not need to @DependsOn BeforeReady services (PreferenceService, DbService, CacheService, DataApiService). The lifecycle container guarantees BeforeReady completes before any WhenReady service starts. Declaring these dependencies is redundant, creates misleading noise in the dependency graph, and may confuse future readers about same-phase coupling. Only use @DependsOn for services within the same phase, or for WhenReady → WhenReady dependencies.
See Dependency Rules for the full matrix and Common Mistakes for a code-level example.
| Wrong Choice | Why It's Wrong | Correct Choice |
|---|---|---|
Using lifecycle for ExportService | No onInit/onStop needed — all work is method-scoped | Direct-import singleton |
Using lifecycle for MessageRepository | Just wraps DB queries; the DB connection belongs to DbService | Direct-import singleton |
Using direct-import for CacheService | Owns a GC timer that needs cleanup on shutdown | Lifecycle |
Manual getInstance() singleton | Lifecycle container manages singletons automatically | @Injectable + application.get() |
Calling application.get() at module scope | Runs before bootstrap — service not yet registered | Call inside onInit() or methods |
Redundant @DependsOn on cross-phase deps (e.g. WhenReady → PreferenceService) | BeforeReady phase is guaranteed to finish before WhenReady starts — declaration is noise and mis-signals coupling | Omit @DependsOn for cross-phase deps; only declare same-phase deps |
src/main/core/lifecycle/ — IoC container, service lifecycle managementsrc/main/core/application/ — Application singleton, service registry, bootstrap orchestrationsrc/main/services/ — Business services registered in the lifecycle systemsrc/main/data/ — Data layer services (Cache, Preference, DataApi)