-
-
Notifications
You must be signed in to change notification settings - Fork 776
Description
Hello all π
I'm pleased to share a new upcoming part in Koin project: Koin Kotlin Compiler Plugin!
A Kotlin Compiler Plugin for Koin with automatic constructor injection. Write single<MyService>() instead of singleOf(::MyService) or single { MyService(get(), get()) } β the plugin handles the wiring at compile-time.
A native Kotlin Compiler Plugin that replaces the KSP compiler in Koin Annotations. Use @Singleton/@factory annotations (and others) β all resolved at compile-time by the Kotlin compiler, no KSP required.
Note: this note will be updated to keep you posted with the latest info, and let you help us test the latest Koin Plugin version π
Koin DSL & Annotations will get updates, thanks to the new plugin.
Here is an overview of what's coming π
Part 1: DSL Transformations
Write concise DSL, get optimized code:
single<MyService>()
// or
single(::MyService)
// Transformed to β single { MyService(get(), get()) }Supported DSL Functions
| Function | Receiver | Description |
|---|---|---|
| single(::T) / single() | Module | Singleton definition |
| factory(::T) / factory() | Module | Factory definition |
| viewModel(::T) / viewModel() | Module | ViewModel definition |
| scoped(::T) / scoped() | ScopeDSL | Scoped definition |
| create(::T) | Scope | Create instance in scope |
Syntax Styles
Constructor reference:
single(::MyService)
factory(::MyRepository)
viewModel(::MyViewModel)Type parameter (even simpler!):
single<MyService>()
factory<MyRepository>()
viewModel<MyViewModel>()Function reference:
fun createService(repo: Repository, config: Config? = null) = MyService(repo, config)
single(::createService)With options:
single<MyService>() withOptions { createdAtStart() }Interface binding:
// don't expose implementation
single<MyInterface> { create(::MyInterfaceImpl) }
// or with bind
single<MyInterfaceImpl>() bind MyInterface::classScoped definitions:
// works with all scopes and scope archetypes
scope(named("myScope")) {
scoped<SessionManager>()
factory<ScopedFactory>()
}Smart Parameter Resolution
| Parameter Type | Generated Code |
|---|---|
| val repo: Repository | get() |
| val config: Config? = null | getOrNull() |
| val lazy: Lazy | inject() |
| @nAmed("prod") val db: Database | get(named("prod")) |
| @InjectedParam val id: Int | it.get() |
(No need of named() written manually)
DSL Example
val appModule = module {
single<ApiClient>()
single(::Repository)
factory<GetUserUseCase>()
viewModel<UserViewModel>()
scope(named("session")) {
scoped<SessionManager>()
}
}
startKoin {
modules(appModule)
}Part 2: Annotation-Driven Configuration
Define your dependency graph declaratively with annotations.
Class Annotations
| Annotation | Effect |
|---|---|
| @singleton | Generates single() |
| @factory | Generates factory() |
| @KoinViewModel | Generates viewModel() |
| @Scoped | Generates scoped() |
| @scope(T::class) | Associates with scope |
| @nAmed("qualifier") | Adds qualifier to definition |
Module Annotations
| Annotation | Effect |
|---|---|
| @module | Marks class as module container |
| @componentscan | Auto-scans package for annotated classes |
| @module(includes = [...]) | Includes other modules |
| @configuration | Enables cross-module discovery |
Parameter Annotations
| Annotation | Effect |
|---|---|
| @nAmed("qualifier") | Injects with qualifier |
| @InjectedParam | Gets value from parametersOf() |
Annotation Example
@Module(includes = [NetworkModule::class])
@ComponentScan
class AppModule {
@Singleton
fun provideAnalytics(repo: Repository) = Analytics(repo)
}
@Singleton
class Repository(val api: ApiClient)
@Factory
class GetUserUseCase(val repo: Repository)
@KoinViewModel
class UserViewModel(val useCase: GetUserUseCase) : ViewModel()
@Scope(UserSession::class)
@Scoped
class UserPreferencesApplication Boostrap & Modules
@KoinApplication(modules = [AppModule::class])
object MyApp
fun main() {
// Start Koin with "MyApp" configuration, loading all associated modules
startKoin<MyApp> {
printLogger()
}
}Cross-Module Discovery with @configuration
Modules marked with @configuration are automatically discovered across project dependencies:
// feature-module
@Module @ComponentScan @Configuration
class FeatureModule
@Singleton
class FeatureService
// app-module (depends on feature-module)
@KoinApplication // No explicit modules needed!
object MyApp
fun main() {
startKoin<MyApp> { }
// FeatureService is available - FeatureModule was auto-discovered!
}Part 3: Compile Safety
for both Koin DSL & Annotations!
What's Coming
- Plugin available on Maven Central (soon)
- worker() for Android WorkManager
- Compile-time dependency graph validation
- full cover of Koin Annotations scope
Feedback will be Welcome!
This is an early preview. We'd love your feedback on the API design and edge cases you encounter.