Core dependency injection framework for Kotlin multiplatform applications with DSL-based configuration and type-safe dependency resolution.
—
Hierarchical scope system for controlling dependency lifecycles and providing isolated dependency contexts for specific application areas. Scopes enable fine-grained resource management and dependency isolation.
Core scope implementation providing isolated dependency container functionality.
/**
* Scoped dependency container with lifecycle management
* @param scopeQualifier - Qualifier identifying the scope type
* @param id - Unique identifier for this scope instance
* @param isRoot - Whether this is a root scope
* @param _koin - Associated Koin instance
*/
class Scope(
val scopeQualifier: Qualifier,
val id: ScopeID,
val isRoot: Boolean = false,
private val _koin: Koin
) {
/**
* Whether this scope has been closed
*/
val closed: Boolean
/**
* Get associated Koin instance
* @return Koin instance
*/
fun getKoin(): Koin
/**
* Close scope and clean up resources
*/
fun close()
}
typealias ScopeID = StringInject dependencies from within a specific scope context.
/**
* Lazy inject dependency from scope
* @param qualifier - Optional qualifier to distinguish instances
* @param mode - Thread safety mode for lazy initialization
* @param parameters - Optional parameters for dependency creation
* @return Lazy delegate for the dependency
*/
inline fun <reified T> Scope.inject(
qualifier: Qualifier? = null,
mode: LazyThreadSafetyMode = LazyThreadSafetyMode.SYNCHRONIZED,
noinline parameters: ParametersDefinition? = null
): Lazy<T>
/**
* Lazy inject dependency from scope with nullable result
* @param qualifier - Optional qualifier to distinguish instances
* @param mode - Thread safety mode for lazy initialization
* @param parameters - Optional parameters for dependency creation
* @return Lazy delegate for nullable dependency
*/
inline fun <reified T> Scope.injectOrNull(
qualifier: Qualifier? = null,
mode: LazyThreadSafetyMode = LazyThreadSafetyMode.SYNCHRONIZED,
noinline parameters: ParametersDefinition? = null
): Lazy<T?>
/**
* Get dependency directly from scope
* @param qualifier - Optional qualifier to distinguish instances
* @param parameters - Optional parameters for dependency creation
* @return Resolved dependency instance
*/
inline fun <reified T> Scope.get(
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
): T
/**
* Get dependency from scope with nullable result
* @param qualifier - Optional qualifier to distinguish instances
* @param parameters - Optional parameters for dependency creation
* @return Resolved dependency instance or null
*/
inline fun <reified T> Scope.getOrNull(
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
): T?
/**
* Get all instances of a type from scope
* @return List of resolved instances
*/
inline fun <reified T> Scope.getAll(): List<T>Usage Examples:
import org.koin.core.scope.Scope
import org.koin.core.qualifier.named
class UserFeature {
private val userScope: Scope = koin.createScope("user-123", named<UserScope>())
fun processUserData() {
// Lazy injection from scope
val userSession: UserSession by userScope.inject()
val userPrefs: UserPreferences by userScope.inject()
// Direct retrieval from scope
val userValidator = userScope.get<UserValidator>()
val userCache = userScope.get<UserCache>(named("memory"))
// Nullable retrieval
val optionalFeature = userScope.getOrNull<OptionalFeature>()
// Get all validators in scope
val allValidators = userScope.getAll<Validator>()
// Process with scoped dependencies
if (userValidator.isValid(userSession.userId)) {
val data = userPrefs.getData()
// Process data...
}
// Clean up scope when done
userScope.close()
}
}Create and manage scopes through the Koin container.
/**
* Create new scope in Koin container
* @param scopeId - Unique identifier for the scope
* @param qualifier - Scope type qualifier
* @param source - Optional source object for linking
* @return New scope instance
*/
fun Koin.createScope(
scopeId: String,
qualifier: Qualifier,
source: Any? = null
): Scope
/**
* Get existing scope by ID
* @param scopeId - Scope identifier
* @return Existing scope instance
* @throws ScopeNotCreatedException if scope doesn't exist
*/
fun Koin.getScope(scopeId: String): Scope
/**
* Get existing scope or null
* @param scopeId - Scope identifier
* @return Existing scope or null
*/
fun Koin.getScopeOrNull(scopeId: String): Scope?
/**
* Delete scope by ID
* @param scopeId - Scope identifier
*/
fun Koin.deleteScope(scopeId: String)
/**
* Get or create scope
* @param scopeId - Scope identifier
* @param qualifier - Scope type qualifier
* @return Existing or new scope instance
*/
fun Koin.getOrCreateScope(scopeId: String, qualifier: Qualifier): ScopeUsage Examples:
import org.koin.core.context.GlobalContext
import org.koin.core.qualifier.named
class ScopeManager {
private val koin = GlobalContext.get()
fun createUserScope(userId: String): Scope {
return koin.createScope(
scopeId = "user-$userId",
qualifier = named<UserScope>()
)
}
fun getUserScope(userId: String): Scope? {
return koin.getScopeOrNull("user-$userId")
}
fun cleanupUserScope(userId: String) {
koin.deleteScope("user-$userId")
}
fun processUser(userId: String) {
// Get or create scope
val scope = koin.getOrCreateScope("user-$userId", named<UserScope>())
// Use scope
val userService = scope.get<UserService>()
userService.processUser(userId)
// Scope remains active for future use
}
}Link scopes together and associate scopes with source objects for automatic cleanup.
/**
* Link this scope to another scope
* @param scope - Target scope to link to
*/
fun Scope.linkTo(scope: Scope)
/**
* Unlink this scope from another scope
* @param scope - Target scope to unlink from
*/
fun Scope.unlink(scope: Scope)
/**
* Get source object associated with this scope
* @return Source object or null
*/
fun <T> Scope.getSource(): T?
/**
* Declare additional instance in scope
* @param instance - Instance to declare
* @param qualifier - Optional qualifier
* @param secondaryTypes - Additional types to bind
* @param allowOverride - Whether to allow overriding existing declaration
*/
inline fun <reified T> Scope.declare(
instance: T,
qualifier: Qualifier? = null,
secondaryTypes: List<KClass<*>>? = null,
allowOverride: Boolean = false
)Usage Examples:
import org.koin.core.scope.Scope
import org.koin.core.qualifier.named
class ActivityScope(private val activity: Activity) {
private val activityScope: Scope = koin.createScope(
scopeId = "activity-${activity.hashCode()}",
qualifier = named<ActivityScope>(),
source = activity // Link scope to activity lifecycle
)
private val featureScope: Scope = koin.createScope(
scopeId = "feature-${activity.hashCode()}",
qualifier = named<FeatureScope>()
)
fun initialize() {
// Link feature scope to activity scope
featureScope.linkTo(activityScope)
// Declare runtime instance in scope
activityScope.declare(
instance = ActivityManager(activity),
qualifier = named("manager")
)
// Bind additional types
activityScope.declare(
instance = CustomLogger(),
secondaryTypes = listOf(Logger::class, Closeable::class)
)
}
fun getFeatureScope(): Scope = featureScope
fun cleanup() {
// Unlink scopes
featureScope.unlink(activityScope)
// Close scopes
featureScope.close()
activityScope.close()
// Get source for final cleanup
val sourceActivity = activityScope.getSource<Activity>()
sourceActivity?.finish()
}
}Access properties from scope with fallback to parent scopes.
/**
* Get property value from scope
* @param key - Property key
* @param defaultValue - Default value if property not found
* @return Property value
*/
fun <T> Scope.getProperty(key: String, defaultValue: T): T
/**
* Get property value from scope
* @param key - Property key
* @return Property value or null
*/
fun <T> Scope.getProperty(key: String): T?
/**
* Set property value in underlying Koin instance
* @param key - Property key
* @param value - Property value
*/
fun Scope.setProperty(key: String, value: Any?)Usage Examples:
import org.koin.core.scope.Scope
class ConfigurableScope(private val scope: Scope) {
fun configure() {
// Get configuration properties
val timeout = scope.getProperty("http.timeout", 30)
val baseUrl = scope.getProperty<String>("api.baseUrl")
val debug = scope.getProperty("debug.enabled", false)
// Set runtime properties
scope.setProperty("session.id", generateSessionId())
scope.setProperty("startup.time", System.currentTimeMillis())
// Use properties for configuration
val httpClient = scope.get<HttpClient> {
parametersOf(baseUrl, timeout)
}
if (debug) {
scope.get<Logger>().info("Debug mode enabled")
}
}
}import org.koin.core.qualifier.named
// Define request scope
val requestScope = named<RequestScope>()
// Module with request-scoped dependencies
val requestModule = module {
scope(requestScope) {
scoped<RequestContext> { RequestContextImpl() }
scoped<UserSession> { UserSessionImpl(get()) }
factory<RequestHandler> { RequestHandlerImpl(get(), get()) }
}
}
// Usage in web controller
class WebController : KoinComponent {
fun handleRequest(request: HttpRequest): HttpResponse {
val scope = getKoin().createScope(
scopeId = request.id,
qualifier = requestScope
)
try {
val handler = scope.get<RequestHandler>()
return handler.process(request)
} finally {
scope.close() // Clean up request resources
}
}
}import org.koin.core.qualifier.named
class FeatureModule {
private val featureScope = named<FeatureScope>()
val module = module {
// Global dependencies
single<Logger> { LoggerImpl() }
// Feature-scoped dependencies
scope(featureScope) {
scoped<FeatureConfig> { FeatureConfigImpl(get()) }
scoped<FeatureService> { FeatureServiceImpl(get(), get()) }
factory<FeatureProcessor> { FeatureProcessorImpl(get()) }
}
}
fun createFeatureScope(featureId: String): Scope {
return GlobalContext.get().createScope(
scopeId = "feature-$featureId",
qualifier = featureScope
)
}
}typealias ScopeID = String
data class ScopeDefinition(
val qualifier: Qualifier,
val definition: Definition<*>,
val secondaryTypes: List<KClass<*>>,
val isCreatedAtStart: Boolean
)
class ScopeRegistry {
fun saveDefinition(scopeQualifier: Qualifier, definition: ScopeDefinition)
fun getScopeDefinition(scopeQualifier: Qualifier): ScopeDefinition?
}
// Scope-related exceptions
class ScopeNotCreatedException(message: String) : RuntimeException(message)
class ScopeAlreadyCreatedException(message: String) : RuntimeException(message)
class ClosedScopeException(message: String) : RuntimeException(message)Install with Tessl CLI
npx tessl i tessl/maven-io-insert-koin--koin-core-jvm