Koin Compiler Plugin
The Koin Compiler Plugin is the recommended approach for all new Kotlin 2.x projects. It's a native Kotlin compiler plugin that powers both DSL and Annotations with auto-wiring, compile-time safety, and cleaner syntax.
What is the Compiler Plugin?
The Koin Compiler Plugin is a native Kotlin Compiler Plugin (K2) - not KSP or annotation processing. It integrates directly with the Kotlin compiler to:
- Auto-detect constructor parameters - No manual
get()calls needed - Transform code at compile-time - Errors caught during build
- Work with both DSL and Annotations - Your choice of style
- Generate no visible files - Cleaner project structure
Why Use the Compiler Plugin?
1. Safer Code
The plugin auto-detects constructor dependencies, reducing manual wiring errors:
// Without Compiler Plugin - easy to make mistakes
val appModule = module {
single { UserService(get(), get(), get()) } // Hope you got the order right!
}
// With Compiler Plugin - auto-wired
val appModule = module {
single<UserService>() // Plugin detects all constructor parameters
}
2. Cleaner Syntax
Less boilerplate, more readable:
| Classic DSL | Compiler Plugin DSL |
|---|---|
singleOf(::MyService) | single<MyService>() |
single { MyService(get(), get()) } | single<MyService>() |
factoryOf(::MyRepo) | factory<MyRepo>() |
viewModelOf(::MyVM) | viewModel<MyVM>() |
scopedOf(::MyPresenter) | scoped<MyPresenter>() |
workerOf(::MyWorker) | worker<MyWorker>() |
3. Compile-Time Analysis
The plugin analyzes your code during compilation:
- Validates constructor parameters
- Detects missing dependencies (verification coming soon)
- Catches errors before runtime
4. DSL & Annotations - Both Equally Powerful
Use whichever style you prefer - the same plugin powers both with identical capabilities:
DSL Style:
val appModule = module {
single<Database>()
single<UserRepository>()
viewModel<UserViewModel>()
}
Annotation Style:
@Singleton
class Database
@Singleton
class UserRepository(private val database: Database)
@KoinViewModel
class UserViewModel(private val repository: UserRepository) : ViewModel()
Getting Started
Setup
Add the Compiler Plugin to your project:
// settings.gradle.kts
plugins {
id("io.insert-koin.compiler.plugin") version "1.0.0" apply false
}
// app/build.gradle.kts
plugins {
id("io.insert-koin.compiler.plugin")
}
Using the Compiler Plugin DSL
Import from the compiler plugin package:
import org.koin.plugin.module.dsl.*
import org.koin.dsl.module
val appModule = module {
single<Database>()
single<ApiClient>()
single<UserRepository>()
viewModel<UserViewModel>()
}
The Compiler Plugin DSL is in org.koin.plugin.module.dsl. Classic DSL remains in org.koin.dsl.
Using Annotations
Annotations work the same as before:
@Singleton
class Database
@Singleton
class ApiClient
@Singleton
class UserRepository(
private val database: Database,
private val apiClient: ApiClient
)
@KoinViewModel
class UserViewModel(private val repository: UserRepository) : ViewModel()
@Module
@ComponentScan("com.myapp")
class AppModule
How It Works
The Compiler Plugin operates in two phases:
1. FIR Phase (Analysis)
During the Frontend Intermediate Representation phase, the plugin:
- Analyzes your module definitions
- Detects constructor parameters
- Validates dependency declarations
2. IR Phase (Transformation)
During the Intermediate Representation phase, the plugin:
- Generates proper
get()calls for each parameter - Handles qualifiers (
@Named) - Handles injected parameters (
@InjectedParam) - Handles nullable and Lazy types
What Gets Generated
When you write:
single<UserRepository>()
The plugin transforms it to:
single { UserRepository(get(), get()) } // Parameters auto-detected
For more complex cases:
// Your code
@Singleton
class MyService(
val required: RequiredDep,
val optional: OptionalDep?,
@Named("special") val named: NamedDep,
val lazy: Lazy<LazyDep>,
@InjectedParam val param: String
)
The plugin generates proper handling for each parameter type:
- Required:
get() - Optional:
getOrNull() - Named:
get(named("special")) - Lazy:
inject() - InjectedParam:
params.get()
Compiler Plugin DSL Reference
Definition Types
import org.koin.plugin.module.dsl.*
val appModule = module {
// Singleton - one instance
single<MyService>()
// Factory - new instance each time
factory<MyPresenter>()
// Scoped - instance per scope
scope<MyActivity> {
scoped<ActivityPresenter>()
}
// ViewModel
viewModel<MyViewModel>()
// Worker (Android WorkManager)
worker<MyWorker>()
}
With Qualifiers
val appModule = module {
single<Database>(named("local"))
single<Database>(named("remote"))
}
With Parameters
Parameters passed at injection time:
class UserPresenter(
@InjectedParam val userId: String,
val repository: UserRepository // Auto-injected
)
val appModule = module {
factory<UserPresenter>()
}
// Usage
val presenter: UserPresenter = get { parametersOf("user123") }
Interface Binding
val appModule = module {
single<UserRepositoryImpl>() bind UserRepository::class
// Or multiple bindings
single<MyServiceImpl>() binds arrayOf(
ServiceA::class,
ServiceB::class
)
}
Annotations Reference
Definition Annotations
| Annotation | Description |
|---|---|
@Singleton / @Single | Single instance |
@Factory | New instance each time |
@Scoped | Instance per scope |
@KoinViewModel | Android ViewModel |
@KoinWorker | Android WorkManager Worker |
Parameter Annotations
| Annotation | Description |
|---|---|
@Named("qualifier") | Named qualifier |
@InjectedParam | Runtime parameter (via parametersOf()) |
@Property("key") | Koin property value |
@Provided | External dependency (skip validation) |
Module Annotations
| Annotation | Description |
|---|---|
@Module | Declares a Koin module |
@ComponentScan("package") | Scan package for annotated classes |
@Configuration | Auto-discovered module |
Comparison: Three Approaches
┌─────────────────────────────────────────────────────────────────────────┐
│ ⭐ COMPILER PLUGIN DSL (Recommended) │
│ Package: org.koin.plugin.module.dsl │
│ ───────────────────────────────────────────────────────────────────── │
│ single<MyService>() │
│ factory<MyRepo>() │
│ viewModel<MyVM>() │
│ │
│ ✓ Auto-detects dependencies │
│ ✓ Compile-time analysis │
│ ✓ Cleanest syntax │
├─────────────────────────────────────────────────────────────────────────┤
│ ✅ CLASSIC DSL (Fully Supported) │
│ Package: org.koin.dsl │
│ ───────────────────────────────────────────────────────────────────── │
│ singleOf(::MyService) │
│ single { MyService(get(), get()) } │
│ viewModelOf(::MyVM) │
│ │
│ ✓ Works with any Kotlin version │
│ ✓ Full control over wiring │
│ ✓ Can migrate to Plugin DSL when ready │
├─────────────────────────────────────────────────────────────────────────┤
│ ⚠️ KSP ANNOTATIONS (Deprecated) │
│ ───────────────────────────────────────────────────────────────────── │
│ Uses koin-ksp-compiler │
│ Same annotations as Compiler Plugin │
│ │
│ ⚠ Migrate to Compiler Plugin │
│ ⚠ Will be removed in future version │
└─────────────────────────────────────────────────────────────────────────┘
Migration
From Classic DSL
If you're using classic DSL, migration is optional but recommended:
- Add the Compiler Plugin to Gradle
- Update imports to
org.koin.plugin.module.dsl.* - Replace
singleOf(::Class)withsingle<Class>() - Remove manual
get()calls
See Migrating from DSL to Compiler Plugin.
From KSP Annotations
If you're using KSP, migration is recommended now:
- Update Kotlin to 2.x
- Replace
koin-ksp-compilerwith Compiler Plugin - Your annotations stay the same - no code changes!
- Delete generated files
See Migrating from KSP to Compiler Plugin.
Requirements
- Kotlin 2.x (K2 compiler)
- Gradle 8.x+
Configuration Options
// build.gradle.kts
koinCompiler {
// Options will be documented here
}
Classic DSL: Still Fully Supported
The Compiler Plugin doesn't replace Classic DSL - it adds analysis and generation on top. Classic DSL remains fully supported:
// Still works perfectly
val appModule = module {
singleOf(::Database)
singleOf(::ApiClient)
single { CustomService(get(), get(), configValue) } // Custom logic
viewModelOf(::UserViewModel)
}
Use Classic DSL when you need:
- Custom factory logic
getOrNull()for optional dependencies- Conditional instantiation
- Backward compatibility with Kotlin 1.x
Next Steps
- Setup Guide - Detailed setup instructions
- DSL Reference - Complete DSL documentation
- Annotations Reference - Complete annotations documentation
- Migration Guides - Upgrade your project