0
# Component Integration
1
2
Component interfaces and extension functions for seamless dependency injection integration in your classes.
3
4
## Capabilities
5
6
### KoinComponent Interface
7
8
Basic interface for classes that need access to dependency injection.
9
10
```kotlin { .api }
11
/**
12
* Interface for classes that need access to the Koin container
13
* Provides access to dependency injection functionality
14
*/
15
interface KoinComponent {
16
/**
17
* Get the Koin container instance
18
* @return Koin container for dependency resolution
19
*/
20
fun getKoin(): Koin
21
}
22
```
23
24
**Usage Examples:**
25
26
```kotlin
27
import org.koin.core.component.KoinComponent
28
import org.koin.core.component.inject
29
import org.koin.core.component.get
30
31
class UserController : KoinComponent {
32
// Lazy injection using delegate
33
private val userService: UserService by inject()
34
private val emailService: EmailService by inject(named("primary"))
35
36
fun registerUser(userData: UserData): User {
37
val user = userService.createUser(userData)
38
39
// Direct resolution
40
val validator = get<UserValidator>()
41
validator.validate(user)
42
43
emailService.sendWelcomeEmail(user)
44
return user
45
}
46
47
fun handleSpecialCase() {
48
// Access Koin container directly
49
val koin = getKoin()
50
val specialService = koin.getOrNull<SpecialService>()
51
52
if (specialService != null) {
53
specialService.handleSpecialLogic()
54
}
55
}
56
}
57
```
58
59
### KoinComponent Extension Functions
60
61
Extension functions that provide convenient dependency injection methods for KoinComponent implementations.
62
63
```kotlin { .api }
64
/**
65
* Get a dependency instance from the component's Koin container
66
* @param qualifier - Optional qualifier to distinguish multiple instances
67
* @param parameters - Optional parameters to pass to the factory function
68
* @return Instance of the requested type
69
*/
70
inline fun <reified T : Any> KoinComponent.get(qualifier: Qualifier? = null, noinline parameters: ParametersDefinition? = null): T
71
72
/**
73
* Get a lazy dependency from the component's Koin container
74
* @param qualifier - Optional qualifier to distinguish multiple instances
75
* @param mode - Thread safety mode for the lazy delegate
76
* @param parameters - Optional parameters to pass to the factory function
77
* @return Lazy delegate that resolves the dependency on first access
78
*/
79
inline fun <reified T : Any> KoinComponent.inject(qualifier: Qualifier? = null, mode: LazyThreadSafetyMode = KoinPlatformTools.defaultLazyMode(), noinline parameters: ParametersDefinition? = null): Lazy<T>
80
```
81
82
**Usage Examples:**
83
84
```kotlin
85
import org.koin.core.component.KoinComponent
86
import org.koin.core.component.inject
87
import org.koin.core.component.get
88
import org.koin.core.parameter.parametersOf
89
import org.koin.core.qualifier.named
90
91
class OrderService : KoinComponent {
92
// Lazy injection - resolved on first access
93
private val paymentService: PaymentService by inject()
94
private val inventoryService: InventoryService by inject(named("warehouse"))
95
96
// Lazy injection with parameters
97
private val shippingCalculator: ShippingCalculator by inject {
98
parametersOf("standard")
99
}
100
101
// Note: For optional services, use getKoin().getOrNull() in methods
102
103
fun processOrder(order: Order): OrderResult {
104
// Direct resolution when needed
105
val validator = get<OrderValidator>()
106
validator.validateOrder(order)
107
108
// Use injected services
109
val paymentResult = paymentService.processPayment(order.payment)
110
if (!paymentResult.success) {
111
return OrderResult.PaymentFailed
112
}
113
114
// Check inventory
115
val available = inventoryService.checkAvailability(order.items)
116
if (!available) {
117
return OrderResult.OutOfStock
118
}
119
120
// Calculate shipping
121
val shippingCost = shippingCalculator.calculate(order.address, order.items)
122
123
// Apply promotions if available
124
val promotionService = getKoin().getOrNull<PromotionService>()
125
val finalTotal = promotionService?.applyPromotions(order.total) ?: order.total
126
127
return OrderResult.Success(finalTotal + shippingCost)
128
}
129
}
130
```
131
132
### KoinScopeComponent Interface
133
134
Interface for components that manage their own scope lifecycle.
135
136
```kotlin { .api }
137
/**
138
* Interface for components that manage their own scope
139
* Extends KoinComponent with scope management capabilities
140
*/
141
interface KoinScopeComponent : KoinComponent {
142
/**
143
* The scope associated with this component
144
* Components are responsible for managing their scope lifecycle
145
*/
146
val scope: Scope
147
}
148
```
149
150
**Usage Examples:**
151
152
```kotlin
153
import org.koin.core.component.KoinScopeComponent
154
import org.koin.core.scope.Scope
155
import org.koin.core.qualifier.named
156
157
class WebRequestHandler : KoinScopeComponent {
158
// Create scope for this request handler
159
override val scope: Scope by lazy {
160
getKoin().createScope<RequestScope>("request-${generateId()}")
161
}
162
163
// Inject from the component's scope
164
private val requestContext: RequestContext by scope.inject()
165
private val userSession: UserSession by scope.inject()
166
private val requestLogger: RequestLogger by scope.inject()
167
168
fun handleRequest(request: HttpRequest): HttpResponse {
169
requestLogger.logStart(request)
170
171
try {
172
val user = userSession.getCurrentUser()
173
val response = processRequest(request, user)
174
requestLogger.logSuccess(response)
175
return response
176
} catch (e: Exception) {
177
requestLogger.logError(e)
178
throw e
179
}
180
}
181
182
fun cleanup() {
183
// Close scope when component is done
184
scope.close()
185
}
186
}
187
188
// Usage pattern with try-finally
189
class RequestProcessor {
190
fun processRequest(requestData: RequestData) {
191
val handler = WebRequestHandler()
192
try {
193
val response = handler.handleRequest(requestData.toHttpRequest())
194
// Handle response...
195
} finally {
196
handler.cleanup() // Ensure scope is closed
197
}
198
}
199
}
200
```
201
202
### KoinScopeComponent Extension Functions
203
204
Extension functions that provide scope management utilities for KoinScopeComponent implementations.
205
206
```kotlin { .api }
207
/**
208
* Get the scope ID for any object based on its class name
209
* @param T - Type of the object
210
* @return Generated scope ID string
211
*/
212
fun <T : Any> T.getScopeId(): String
213
214
/**
215
* Get the scope name (type qualifier) for any object
216
* @param T - Type of the object
217
* @return TypeQualifier based on the object's class
218
*/
219
fun <T : Any> T.getScopeName(): TypeQualifier
220
221
/**
222
* Create a scope for a KoinScopeComponent
223
* @param scopeId - Scope identifier (default: generated from object)
224
* @param source - Optional source object
225
* @param scopeArchetype - Optional scope archetype
226
* @return New Scope instance
227
*/
228
fun <T : KoinScopeComponent> T.createScope(scopeId: ScopeID = getScopeId(), source: Any? = null, scopeArchetype: TypeQualifier? = null): Scope
229
230
/**
231
* Create a scope for a KoinScopeComponent with source
232
* @param source - Source object for the scope
233
* @return New Scope instance
234
*/
235
fun <T : KoinScopeComponent> T.createScope(source: Any? = null): Scope
236
237
/**
238
* Get the scope for a KoinScopeComponent or null if not created
239
* @return Existing scope or null
240
*/
241
fun <T : KoinScopeComponent> T.getScopeOrNull(): Scope?
242
243
/**
244
* Create a new scope lazily for a KoinScopeComponent
245
* @return Lazy delegate that creates the scope on first access
246
*/
247
fun <T : KoinScopeComponent> T.newScope(): Lazy<Scope>
248
249
/**
250
* Get existing scope or create a new one lazily for a KoinScopeComponent
251
* @return Lazy delegate that gets or creates the scope on first access
252
*/
253
fun <T : KoinScopeComponent> T.getOrCreateScope(): Lazy<Scope>
254
```
255
256
**Usage Examples:**
257
258
```kotlin
259
import org.koin.core.component.KoinScopeComponent
260
import org.koin.core.component.*
261
262
// Different scope creation patterns
263
class UserSessionManager : KoinScopeComponent {
264
// Option 1: Create scope immediately
265
override val scope: Scope = createScope(source = this)
266
267
private val sessionStore: SessionStore by scope.inject()
268
private val userCache: UserCache by scope.inject()
269
}
270
271
class LazySessionManager : KoinScopeComponent {
272
// Option 2: Create scope lazily
273
override val scope: Scope by newScope()
274
275
private val sessionStore: SessionStore by scope.inject()
276
}
277
278
class AdaptiveSessionManager : KoinScopeComponent {
279
// Option 3: Get or create scope lazily
280
override val scope: Scope by getOrCreateScope()
281
282
private val sessionStore: SessionStore by scope.inject()
283
284
fun initializeSession(userId: String) {
285
// Scope is created here on first access
286
scope.declare(UserId(userId))
287
288
// Generate scope ID for debugging
289
val scopeId = getScopeId()
290
val scopeName = getScopeName()
291
println("Session scope: $scopeName ($scopeId)")
292
}
293
}
294
295
// Usage with explicit scope management
296
class RequestScopedService : KoinScopeComponent {
297
override val scope: Scope by lazy {
298
val myScope = createScope("custom-${System.currentTimeMillis()}")
299
300
// Register cleanup callback
301
myScope.registerCallback(object : ScopeCallback {
302
override fun onScopeCreated(qualifier: Qualifier, scope: Scope) {
303
println("Scope created: ${scope.id}")
304
}
305
306
override fun onScopeClosed(qualifier: Qualifier, scope: Scope) {
307
println("Scope closed: ${scope.id}")
308
}
309
})
310
311
myScope
312
}
313
314
private val requestProcessor: RequestProcessor by scope.inject()
315
316
fun processAndCleanup() {
317
try {
318
requestProcessor.process()
319
} finally {
320
// Check if scope exists before closing
321
getScopeOrNull()?.close()
322
}
323
}
324
}
325
```
326
327
### Component Patterns
328
329
Common patterns for using components effectively.
330
331
**Singleton Component Pattern:**
332
333
```kotlin
334
// Global singleton component
335
object ApplicationServices : KoinComponent {
336
val configService: ConfigService by inject()
337
val logService: LogService by inject()
338
339
fun initialize() {
340
configService.loadConfiguration()
341
logService.initialize()
342
}
343
}
344
345
// Usage
346
ApplicationServices.initialize()
347
val config = ApplicationServices.configService.getConfig("app.name")
348
```
349
350
**Factory Component Pattern:**
351
352
```kotlin
353
// Component factory for creating instances
354
class ComponentFactory : KoinComponent {
355
fun createUserProcessor(userId: String): UserProcessor {
356
return get<UserProcessor> { parametersOf(userId) }
357
}
358
359
fun createApiClient(endpoint: String): ApiClient {
360
return get<ApiClient> { parametersOf(endpoint) }
361
}
362
}
363
364
// Usage
365
val factory = ComponentFactory()
366
val processor = factory.createUserProcessor("user-123")
367
val client = factory.createApiClient("https://api.example.com")
368
```
369
370
**Scoped Component Lifecycle Pattern:**
371
372
```kotlin
373
// Base class for scoped components
374
abstract class ScopedComponent : KoinScopeComponent {
375
abstract val scopeQualifier: Qualifier
376
377
override val scope: Scope by lazy {
378
getKoin().createScope("${scopeQualifier.value}-${generateId()}", scopeQualifier)
379
}
380
381
open fun initialize() {
382
// Subclasses can override for initialization
383
}
384
385
open fun cleanup() {
386
if (!scope.closed) {
387
scope.close()
388
}
389
}
390
}
391
392
// Request-scoped component
393
class RequestComponent : ScopedComponent() {
394
override val scopeQualifier = named("request")
395
396
private val requestHandler: RequestHandler by scope.inject()
397
private val requestValidator: RequestValidator by scope.inject()
398
399
override fun initialize() {
400
// Request-specific initialization
401
scope.declare(RequestId(generateRequestId()))
402
}
403
}
404
405
// Usage with automatic cleanup
406
inline fun <T> withRequestComponent(block: (RequestComponent) -> T): T {
407
val component = RequestComponent()
408
return try {
409
component.initialize()
410
block(component)
411
} finally {
412
component.cleanup()
413
}
414
}
415
416
// Usage
417
withRequestComponent { component ->
418
val result = component.requestHandler.handle(request)
419
// Component is automatically cleaned up
420
result
421
}
422
```
423
424
## Type Definitions
425
426
```kotlin { .api }
427
/**
428
* Base interface for dependency injection components
429
*/
430
interface KoinComponent {
431
fun getKoin(): Koin
432
}
433
434
/**
435
* Interface for components with scope management
436
*/
437
interface KoinScopeComponent : KoinComponent {
438
val scope: Scope
439
}
440
441
/**
442
* Generate a unique ID for scopes and components
443
* @return Generated unique identifier string
444
*/
445
fun generateId(): String
446
447
/**
448
* Type alias for type-based qualifiers
449
*/
450
class TypeQualifier : Qualifier {
451
val type: KClass<*>
452
}
453
```