Koin is a pragmatic lightweight dependency injection framework for Kotlin developers, providing core dependency injection functionality for Kotlin Multiplatform projects.
—
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.
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.() -> UnitThe koinApplication function creates a new KoinApplication instance with optional configuration.
val app = koinApplication {
modules(listOf(appModule, networkModule))
properties(mapOf("api.url" to "https://api.example.com"))
logger(PrintLogger())
}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()
}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))
}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")
)
}
}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)
}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() }
}val app = koinApplication {
allowOverride(true) // Allow overriding existing definitions
modules(baseModule, overrideModule)
}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?// 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()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>()
}
}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()
}
}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()
}
}
}
}class KoinApplicationAlreadyStartedException(message: String) : RuntimeException(message)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
}
}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
}
}val testModule = module {
single<UserRepository> { MockUserRepository() }
single<EmailService> { MockEmailService() }
}
val testApp = koinApplication {
allowOverride(true)
modules(productionModule, testModule) // testModule overrides production
}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()) }
}// 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