CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-insert-koin--koin-core

Koin is a pragmatic lightweight dependency injection framework for Kotlin developers, providing core dependency injection functionality for Kotlin Multiplatform projects.

Pending
Overview
Eval results
Files

components.mddocs/

Component Integration

Koin provides the KoinComponent interface and extension functions to integrate dependency injection into your Kotlin classes. This allows any class to participate in the Koin dependency injection system.

KoinComponent Interface

interface KoinComponent {
    fun getKoin(): Koin
}

The KoinComponent interface is a marker interface that provides access to the Koin instance. Any class implementing this interface can use Koin's dependency injection features.

Basic Usage

class UserController : KoinComponent {
    private val userService: UserService = get()
    
    fun createUser(userData: UserData) {
        userService.create(userData)
    }
}

Dependency Injection Methods

get() - Direct Injection

inline fun <reified T : Any> KoinComponent.get(
    qualifier: Qualifier? = null,
    noinline parameters: ParametersDefinition? = null
): T

Immediately resolves and returns an instance of the requested type.

Parameters:

  • qualifier: Optional qualifier to distinguish between multiple implementations
  • parameters: Optional parameters to pass to the definition function

inject() - Lazy Injection

inline fun <reified T : Any> KoinComponent.inject(
    qualifier: Qualifier? = null,
    mode: LazyThreadSafetyMode = KoinPlatformTools.defaultLazyMode(),
    noinline parameters: ParametersDefinition? = null
): Lazy<T>

Returns a lazy delegate that resolves the instance on first access.

Parameters:

  • qualifier: Optional qualifier to distinguish between multiple implementations
  • mode: Lazy thread safety mode (platform-specific default)
  • parameters: Optional parameters to pass to the definition function

Usage Examples

class OrderService : KoinComponent {
    // Direct injection - resolved immediately
    private val database: Database = get()
    
    // Lazy injection - resolved on first access
    private val emailService: EmailService by inject()
    
    // With qualifiers
    private val primaryCache: Cache = get(named("primary"))
    private val secondaryCache: Cache by inject(named("secondary"))
    
    // With parameters
    private fun getValidator(type: String): Validator {
        return get { parametersOf(type) }
    }
}

KoinScopeComponent Interface

interface KoinScopeComponent : KoinComponent {
    val scope: Scope
}

KoinScopeComponent extends KoinComponent to provide scoped dependency injection. Classes implementing this interface have their own scope for managing lifecycle-aware dependencies.

Scope Management Functions

fun <T : Any> T.getScopeId(): ScopeID
fun <T : Any> T.getScopeName(): TypeQualifier

fun <T : KoinScopeComponent> T.createScope(
    scopeId: ScopeID = getScopeId(),
    source: Any? = null,
    scopeArchetype: TypeQualifier? = null
): Scope

fun <T : KoinScopeComponent> T.createScope(source: Any? = null): Scope
fun <T : KoinScopeComponent> T.getScopeOrNull(): Scope?

Usage Example

class UserSession : KoinScopeComponent {
    override val scope: Scope = createScope()
    
    // Inject from the component's scope
    private val sessionData: SessionData by scope.inject()
    private val userPreferences: UserPreferences = scope.get()
    
    fun logout() {
        // Clean up scoped dependencies
        scope.close()
    }
}

Integration Patterns

Property Injection

class MyService : KoinComponent {
    // Lazy properties
    private val repository by inject<UserRepository>()
    private val config by inject<AppConfig>()
    private val logger by inject<Logger>(named("service"))
    
    fun doWork() {
        logger.info("Starting work")
        val users = repository.findAll()
        // ...
    }
}

Constructor Injection Alternative

While Koin primarily uses property injection, you can also resolve dependencies in constructors:

class MyService : KoinComponent {
    private val repository: UserRepository
    private val config: AppConfig
    
    init {
        repository = get()
        config = get()
    }
}

Conditional Injection

class MyService : KoinComponent {
    private val logger: Logger by lazy {
        if (BuildConfig.DEBUG) {
            get<Logger>(named("debug"))
        } else {
            get<Logger>(named("production"))
        }
    }
}

Parameter Handling

ParametersHolder

class ParametersHolder(private val values: Array<out Any?>) {
    inline fun <reified T> get(index: Int = 0): T
    inline fun <reified T> getOrNull(index: Int = 0): T?
    fun size(): Int
}

fun parametersOf(vararg values: Any?): ParametersHolder

Using Parameters

class DocumentService : KoinComponent {
    fun processDocument(documentType: String, metadata: Map<String, Any>) {
        val processor: DocumentProcessor = get { 
            parametersOf(documentType, metadata) 
        }
        processor.process()
    }
}

// In module definition
val documentModule = module {
    factory<DocumentProcessor> { params ->
        val type = params.get<String>(0)
        val metadata = params.get<Map<String, Any>>(1)
        when (type) {
            "pdf" -> PDFProcessor(metadata)
            "word" -> WordProcessor(metadata)
            else -> GenericProcessor(metadata)
        }
    }
}

Error Handling

Common exceptions when using components:

class NoBeanDefFoundException(message: String) : RuntimeException(message)
class InstanceCreationException(message: String, cause: Throwable?) : RuntimeException(message, cause)
class ClosedScopeException(message: String) : RuntimeException(message)

Safe Injection

class MyService : KoinComponent {
    fun safeGetService(): UserService? {
        return try {
            get<UserService>()
        } catch (e: NoBeanDefFoundException) {
            null
        }
    }
}

Testing with Components

class UserControllerTest : KoinComponent {
    
    @Before
    fun setup() {
        startKoin {
            modules(testModule)
        }
    }
    
    @Test
    fun testUserCreation() {
        val controller = UserController()
        // Controller will use test dependencies
        controller.createUser(testUserData)
    }
    
    @After
    fun teardown() {
        stopKoin()
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-io-insert-koin--koin-core

docs

application.md

components.md

index.md

module-dsl.md

scopes.md

tile.json