
Compile-time dependency injection compositor offering annotation-driven DI, graph validation at compile time, generated entry points, singleton support, and fast incremental builds for safe, efficient dependency wiring.
Spike is a Kotlin Multiplatform dependency injection compositor that ensures compile-time safety and fast, incremental compilation through KSP. It is designed to be straightforward to use and universally applicable across all Kotlin platforms.
Spike uses annotations to define your dependency graph. The core annotations are:
@Inject: Marks a constructor for dependency injection.@Include: Includes a class in the dependency graph.@Singleton: Marks a class as a singleton.@EntryPoint: Defines an entry point for the dependency graph.Here's an example of how to define your components using the coffee example:
// In Heater.kt
interface Heater {
fun on()
fun off()
val isHot: Boolean
}
// In ElectricHeater.kt
@Include(bindAs = Heater::class)
class ElectricHeater(
private val logger: CoffeeLogger
) : Heater {
// ...
}
// In CoffeeMaker.kt
@Include
class CoffeeMaker(
private val logger: CoffeeLogger,
private val heater: Heater,
private val pump: Pump
) {
// ...
}To access your dependency graph, you need to create an entry point. This is done by creating an interface and annotating it with @EntryPoint:
@EntryPoint
interface CoffeeShop {
fun coffeeMaker(): CoffeeMaker
companion object
}After you build your project, Spike will generate an implementation of your entry point. You can then use this to access your dependencies:
val coffeeShop = CoffeeShop() // invoke extension on companion object
val coffeeMaker = coffeeShop.coffeeMaker()
coffeeMaker.brew()Spike is a Kotlin Multiplatform dependency injection compositor that ensures compile-time safety and fast, incremental compilation through KSP. It is designed to be straightforward to use and universally applicable across all Kotlin platforms.
Spike uses annotations to define your dependency graph. The core annotations are:
@Inject: Marks a constructor for dependency injection.@Include: Includes a class in the dependency graph.@Singleton: Marks a class as a singleton.@EntryPoint: Defines an entry point for the dependency graph.Here's an example of how to define your components using the coffee example:
// In Heater.kt
interface Heater {
fun on()
fun off()
val isHot: Boolean
}
// In ElectricHeater.kt
@Include(bindAs = Heater::class)
class ElectricHeater(
private val logger: CoffeeLogger
) : Heater {
// ...
}
// In CoffeeMaker.kt
@Include
class CoffeeMaker(
private val logger: CoffeeLogger,
private val heater: Heater,
private val pump: Pump
) {
// ...
}To access your dependency graph, you need to create an entry point. This is done by creating an interface and annotating it with @EntryPoint:
@EntryPoint
interface CoffeeShop {
fun coffeeMaker(): CoffeeMaker
companion object
}After you build your project, Spike will generate an implementation of your entry point. You can then use this to access your dependencies:
val coffeeShop = CoffeeShop() // invoke extension on companion object
val coffeeMaker = coffeeShop.coffeeMaker()
coffeeMaker.brew()