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

application.mddocs/

Application Configuration

The KoinApplication class is the main entry point for configuring and starting a Koin dependency injection container. It provides a fluent API for setting up modules, properties, logging, and other application-wide configuration.

KoinApplication Creation

fun koinApplication(
    createEagerInstances: Boolean = true,
    appDeclaration: KoinAppDeclaration? = null
): KoinApplication

fun koinApplication(appDeclaration: KoinAppDeclaration?): KoinApplication
fun koinApplication(configuration: KoinConfiguration?): KoinApplication
fun koinApplication(createEagerInstances: Boolean): KoinApplication

typealias KoinAppDeclaration = KoinApplication.() -> Unit

The koinApplication function creates a new KoinApplication instance with optional configuration.

Basic Usage

val app = koinApplication {
    modules(listOf(appModule, networkModule))
    properties(mapOf("api.url" to "https://api.example.com"))
    logger(PrintLogger())
}

KoinApplication Configuration

class KoinApplication {
    val koin: Koin
    
    fun modules(modules: Module): KoinApplication
    fun modules(vararg modules: Module): KoinApplication
    fun modules(modules: List<Module>): KoinApplication
    
    fun properties(values: Map<String, Any>): KoinApplication
    fun fileProperties(fileName: String = "/koin.properties"): KoinApplication
    fun environmentProperties(): KoinApplication
    
    fun logger(logger: Logger): KoinApplication
    
    fun createEagerInstances()
    fun allowOverride(override: Boolean)
    
    fun close()
}

Module Loading

Load dependency injection modules into the application:

val databaseModule = module {
    single<Database> { DatabaseImpl() }
}

val serviceModule = module {
    single<UserService> { UserServiceImpl(get()) }
}

val app = koinApplication {
    // Single module
    modules(databaseModule)
    
    // Multiple modules with vararg
    modules(databaseModule, serviceModule)
    
    // List of modules
    modules(listOf(databaseModule, serviceModule))
}

Property Configuration

val app = koinApplication {
    // Map of properties
    properties(mapOf(
        "database.url" to "jdbc:h2:mem:test",
        "api.timeout" to 30,
        "feature.enabled" to true
    ))
    
    // Load from file (platform-specific)
    fileProperties("/config/app.properties")
    
    // Load from environment variables
    environmentProperties()
}

// Access properties in definitions
val appModule = module {
    single<DatabaseConfig> {
        DatabaseConfig(
            url = getProperty<String>("database.url"),
            timeout = getProperty<Int>("api.timeout")
        )
    }
}

Logging Configuration

interface Logger {
    fun display(level: Level, message: String)
    fun isAt(level: Level): Boolean
}

enum class Level {
    DEBUG, INFO, WARNING, ERROR, NONE
}

Set up logging to monitor Koin's behavior:

val app = koinApplication {
    logger(PrintLogger(Level.DEBUG))
    modules(appModule)
}

// Custom logger implementation
class CustomLogger : Logger {
    override fun display(level: Level, message: String) {
        println("[$level] $message")
    }
    
    override fun isAt(level: Level): Boolean = true
}

val appWithCustomLogger = koinApplication {
    logger(CustomLogger())
    modules(appModule)
}

Eager Instance Creation

val app = koinApplication {
    modules(appModule)
    // Create all singleton instances marked with createdAtStart = true
    createEagerInstances()
}

// In module definition
val eagerModule = module {
    single<AppConfig>(createdAtStart = true) { AppConfigImpl() }
    single<DatabaseConnection>(createdAtStart = true) { DatabaseConnectionImpl() }
}

Definition Override

val app = koinApplication {
    allowOverride(true)  // Allow overriding existing definitions
    modules(baseModule, overrideModule)
}

Global Context Management

While KoinApplication creates isolated contexts, Koin also provides global context management for simpler usage patterns:

// Platform-specific functions (available on JVM/Android)
fun startKoin(appDeclaration: KoinAppDeclaration): KoinApplication
fun stopKoin()

// Context access
fun GlobalContext.get(): Koin
fun GlobalContext.getOrNull(): Koin?

Global Context Usage

// Start global Koin context
startKoin {
    modules(listOf(appModule, serviceModule))
    logger(PrintLogger())
    properties(mapOf("env" to "production"))
}

class MyService : KoinComponent {
    // Uses global context automatically
    private val repository: Repository by inject()
}

// Stop global context
stopKoin()

Advanced Configuration

Multiple Applications

class MultiAppExample {
    fun setupApplications() {
        // Separate application contexts
        val webApp = koinApplication {
            modules(webModule)
            properties(mapOf("context" to "web"))
        }
        
        val backgroundApp = koinApplication {
            modules(backgroundModule)
            properties(mapOf("context" to "background"))
        }
        
        // Each has its own dependency graph
        val webService = webApp.koin.get<WebService>()
        val bgService = backgroundApp.koin.get<BackgroundService>()
    }
}

Dynamic Module Loading

class DynamicConfiguration {
    fun configureDynamically() {
        val app = koinApplication()
        
        // Load base modules
        app.modules(coreModule)
        
        // Conditionally load additional modules
        if (isWebEnvironment()) {
            app.modules(webModule)
        }
        
        if (isDevelopment()) {
            app.modules(debugModule)
            app.logger(PrintLogger(Level.DEBUG))
        }
        
        app.createEagerInstances()
    }
}

Configuration from External Sources

class ExternalConfiguration {
    fun loadFromConfig(configFile: String) {
        val config = loadConfig(configFile)
        
        val app = koinApplication {
            // Dynamic module selection
            modules(selectModules(config.features))
            
            // Environment-specific properties
            properties(config.properties)
            
            // Conditional features
            if (config.loggingEnabled) {
                logger(PrintLogger(config.logLevel))
            }
            
            if (config.eagerLoading) {
                createEagerInstances()
            }
        }
    }
}

Error Handling

class KoinApplicationAlreadyStartedException(message: String) : RuntimeException(message)

Safe Application Management

class SafeApplicationManager {
    private var currentApp: KoinApplication? = null
    
    fun startSafely(config: KoinAppDeclaration): Boolean {
        return try {
            currentApp?.close()
            currentApp = koinApplication(config)
            true
        } catch (e: Exception) {
            println("Failed to start Koin application: ${e.message}")
            false
        }
    }
    
    fun stopSafely() {
        currentApp?.close()
        currentApp = null
    }
}

Testing Support

Test Application Setup

class TestApplicationSetup {
    lateinit var testApp: KoinApplication
    
    @Before
    fun setup() {
        testApp = koinApplication {
            modules(testModule)
            properties(mapOf(
                "database.url" to "jdbc:h2:mem:test",
                "mock.services" to true
            ))
        }
    }
    
    @After
    fun teardown() {
        testApp.close()
    }
    
    @Test
    fun testWithKoin() {
        val service = testApp.koin.get<UserService>()
        // Test with injected dependencies
    }
}

Mock Module Override

val testModule = module {
    single<UserRepository> { MockUserRepository() }
    single<EmailService> { MockEmailService() }
}

val testApp = koinApplication {
    allowOverride(true)
    modules(productionModule, testModule)  // testModule overrides production
}

Performance Considerations

Lazy vs Eager Loading

val optimizedApp = koinApplication {
    modules(coreModule)
    
    // Only create essential services eagerly
    // Non-critical services remain lazy
    createEagerInstances()
}

val coreModule = module {
    // Critical services - created at startup
    single<DatabaseConnection>(createdAtStart = true) { 
        DatabaseConnectionImpl() 
    }
    
    // Non-critical services - created on demand
    single<ReportGenerator> { ReportGeneratorImpl(get()) }
}

Module Organization

// Organize modules by feature for better performance
val featureModules = listOf(
    authenticationModule,
    userManagementModule,
    reportingModule
)

val app = koinApplication {
    modules(coreModule)  // Load core first
    modules(featureModules)  // Then features
}

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