0%

依赖注入 - Koin 2.1.6 源码浅析

Dagger2 缺点

  1. 学习和科普成本极高,API使用非常繁琐。
  2. 配置越多,生成的辅助代码越多,会导致:
    • 增加编译时间。
    • 增加Apk体积。

Koin 优势

  1. 开发者需要理解的概念很少,最核心就是理解Scope一个概念,其他看看文档个和源码可以秒懂。
  2. 在kotlin语法下(如扩展、委托),API极度简洁、无感、易用。
  3. 无反射,无运行时性能损耗。
  4. 没有辅助代码生成,纯粹在代码层做配置,所以不会增长编译时间,不会增大APK体积。

Koin基本原理

  • 要注入的对象都定义在Module对象中,一个Module包含多个对象。
  • Module对象都存储在一个的Scope对象里,一个Scope包含多个Module实例。
  • 所有的Scope都存储在一个Koin对象里,一个Koin包含多个Scope实例。
  • Koin对象就是一个容器,可以保持一个单例,也可以创建多个Koin实例。
  • 获取要注入的对象,先获取容器,再查找目标Scope,最后调用Scope的get()方法获取对象。

Scope代表作用域,不同作用域下定义两个一样的对象声明,最终会产生不同的对象。

通过Kotlin的委托、扩展、DSL等语法,可以把对象的注入获取封装成简洁、无感知的形式。

其他所有的功能扩展,都是以上面的基本流程展开的,有了主线逻辑,其他都很好懂。

Koin是怎么用的?

看官方文档介绍:

https://insert-koin.io/docs/quickstart/kotlin

要提供的类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* A class to hold our message data
*/
data class HelloMessageData(val message : String = "Hello Koin!")

/**
* Hello Service - interface
*/
interface HelloService {
fun hello(): String
}

/**
* Hello Service Impl
* Will use HelloMessageData data
*/
class HelloServiceImpl(private val helloMessageData: HelloMessageData) : HelloService {
override fun hello() = "Hey, ${helloMessageData.message}"
}

HelloApplication要通过Koin注入对象。

1
2
3
4
5
6
7
8
9
10
11
12
/**
* HelloApplication - Application Class
* use HelloService
*/
class HelloApplication : KoinComponent {

// Inject HelloService
val helloService by inject<HelloService>()

// display our data
fun sayHello() = println(helloService.hello())
}

在Koin中声明可以注入的对象:

1
2
3
4
val helloModule = module {
single { HelloMessageData() }
single { HelloServiceImpl(get()) as HelloService }
}

初始化Koin,直接调用代码,自动注入:

1
2
3
4
5
6
7
8
9
10
fun main(vararg args: String) {
startKoin {
// use Koin logger
printLogger()
// declare modules
modules(helloModule)
}

HelloApplication().sayHello()
}

Koin项目地址

https://github.com/InsertKoinIO/koin

由于每个版本源码结构变化较大,下面的源码分析基于Koin版本是2.1.6。
即基于commit id 为bbf2b7ca84c3dfda6b1894fc0bfcc7ed0fbc4d89的源码进行分析。

Koin的入口在哪?

首先需要在Application的onCreate()去初始化Koin配置。

1
2
3
4
5
6
startKoin {
//声明Android上下文
androidContext(this@MyApplication)
//声明要使用的模块
modules(myAppModules)
}

最主要的是要声明使用的Module,Module中提供了要注入的对象。

startKoin()做了什么?

先看startKoin()源码,startKoin()代码位于ContextFunctions.kt:

1
2
3
4
5
6
7
8
9
10
11
/**
* Start a Koin Application as StandAlone
*/
fun startKoin(koinContext: KoinContext = GlobalContext(), appDeclaration: KoinAppDeclaration): KoinApplication {
KoinContextHandler.register(koinContext)
val koinApplication = KoinApplication.init()
KoinContextHandler.start(koinApplication)
appDeclaration(koinApplication)
koinApplication.createEagerInstances()
return koinApplication
}

KoinAppDeclaration是做什么的?

KoinAppDeclaration 的定义是:
typealias KoinAppDeclaration = KoinApplication.() -> Unit

参数KoinAppDeclaration是一个以KoinApplication为接受者的函数,在函数大括号里调用的方法,如androidContext()、modules()等,都是KoinApplication的成员函数或扩展函数。

KoinContext 是做什么的?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* Component that hold the Koin instance
*/
interface KoinContext {
/**
* Get Koin instance
*/
fun get(): Koin

/**
* Get Koin instance or null
*/
fun getOrNull(): Koin?

/**
* Start a Koin Application
*/
fun setup(koinApplication: KoinApplication)

/**
* Stop current Koin instance
*/
fun stop()
}

根据注释,KoinContext是持有Koin实例的。

startKoin方法中默认实现是GlobalContext,看看GlobalContext的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

/**
* Global context - current Koin Application available globally
*
* Support to help inject automatically instances once KoinApp has been started
*
* @author Arnaud Giuliani
*/
class GlobalContext : KoinContext {
private var _koin: Koin? = null

override fun get(): Koin = _koin ?: error("KoinApplication has not been started")

override fun getOrNull(): Koin? = _koin

override fun setup(koinApplication: KoinApplication) = synchronized(this) {
if (_koin != null) {
throw KoinAppAlreadyStartedException("A Koin Application has already been started")
}
_koin = koinApplication.koin
}

override fun stop() = synchronized(this) {
_koin?.close()
_koin = null
}
}

主要就是存储Koin对象存储为_koin成员变量。

KoinContextHandler.register(koinContext) 做了什么?

KoinContextHandler类也很短,看源码很简单,就是持有KoinContext的对象实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
* Help hold any implementation of KoinContext
*/
object KoinContextHandler {

private var _context: KoinContext? = null

private fun getContext(): KoinContext {
return _context ?: error("No Koin Context configured. Please use startKoin or koinApplication DSL. ")
}

/**
* Retrieve current KoinContext
*/
fun get(): Koin = getContext().get()

/**
* Retrieve current KoinContext or null
*/
fun getOrNull(): Koin? = _context?.getOrNull()

/**
* Register new KoinContext
*
* @throws IllegalStateException if already registered
*/
fun register(koinContext: KoinContext) = synchronized(this) {
if (_context != null) {
error("A KoinContext is already started")
}
_context = koinContext
}

/**
* Start a Koin Application on current KoinContext
*/
fun start(koinApplication: KoinApplication) {
getContext().setup(koinApplication)
}

/**
* Stop current KoinContext & clear it
*/
fun stop() {
_context?.stop()
_context = null
}
}

这么设计有什么好处?

可以看到KoinContextHandler是object修饰的,是单例。

我们是可以通过这个单例在任意位置获取到Koin对象的。

具体的应用在KoinComponent:

1
2
3
interface KoinComponent {
fun getKoin(): Koin = KoinContextHandler.get()
}

只要是实现了KoinComponent接口的类,就可以通过getKoin()获得默认的Koin对象,或者自己提供一个Koin对象也行。

什么时候需要自己提供一个Koin对象?

比如要做Mock测试,可以快速提供一个模拟数据的Koin容器对象,快速做调试。

获取Koin对象有什么用?

这个后面就知道了,因为要注入的对象都在Koin对象里,所以通过Koin对象就可以获取要注入的对象。

KoinApplication.init() 做了什么?

1
2
3
4
5
6
7
8
9
/**
* Create a new instance of KoinApplication
*/
@JvmStatic
fun init(): KoinApplication {
val app = KoinApplication()
app.init()
return app
}

创建一个KoinApplication 对象,调用其init()方法,然后返回KoinApplication 对象。

KoinApplication的init实例方法做了什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Koin Application
* Help prepare resources for Koin context
*
* @author Arnaud Giuliani
*/
class KoinApplication private constructor() {
val koin = Koin()

internal fun init() {
koin._scopeRegistry.createRootScopeDefinition()
}
// ...
}
  • KoinApplication 中创建了一个Koin类型的属性。
  • init()方法调用koin._scopeRegistry.createRootScopeDefinition()

Koin._scopeRegistry是干什么的?

1
2
3
4
class Koin {  
val _scopeRegistry = ScopeRegistry(this)
//...
}

Koin 创建时就创建了ScopeRegistry。

ScopeRegistry顾名思义就是一个Scope花名册,汇总所有Scope的地方。

因为内部有一个Map,Key是Scope的唯一标识,Value是Scope的定义(即ScopeDefinition对象)。

一个Koin对象对应一个ScopeRegistry对象,管理所有Scope。

一个KoinApplication 对象对应一个Koin对象。

ScopeRegistry.createRootScopeDefinition()干了什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* Scope Registry
* create/find scopes for Koin
*
* @author Arnaud Giuliani
*/
class ScopeRegistry(private val _koin: Koin) {
private val _scopeDefinitions = HashMap<QualifierValue, ScopeDefinition>()
var _rootScopeDefinition: ScopeDefinition? = null

internal fun createRootScopeDefinition() {
val scopeDefinition = ScopeDefinition.rootDefinition()
_scopeDefinitions[ScopeDefinition.ROOT_SCOPE_QUALIFIER.value] =
scopeDefinition
_rootScopeDefinition = scopeDefinition
}
// ...
}

class ScopeDefinition {
// ...
companion object {
const val ROOT_SCOPE_ID = "-Root-"
val ROOT_SCOPE_QUALIFIER = _q(ROOT_SCOPE_ID)
fun rootDefinition() = ScopeDefinition(ROOT_SCOPE_QUALIFIER, isRoot = true)
}}
}

fun _q(name: String) = StringQualifier(name)

data class StringQualifier(override val value: QualifierValue) : Qualifier {
override fun toString(): String {
return value
}
}
  • 创建了一个ScopeDefinition对象,名字叫-Root-
  • 把Root ScopeDefinition存储到 _scopeDefinitions 这个map中。
  • 把Root ScopeDefinition存储到 _rootScopeDefinition 变量中。

也就是把RootScope和普通的Scope分开存储,为什么要分开存储呢?

到后面才知道,因为如果规定对象是在某一个作用域Scope下面,那么这个对象的存储都放在Scope对象里管理,但是没有声明Scope的对象,那么它其实也可以被一个默认的Scope管理,这样代码就统一了,不用多写重复的逻辑,这就是Root Scope。

KoinContextHandler.start(koinApplication)做了什么?

根据上面KoinContextHandler和GlobalContext源码,就是把koinApplication对象里的Koin对象保存在GlobalContext的_koin属性里。

appDeclaration(koinApplication)做了什么?

appDeclaration就是调用startKoin方法时传的大括号lambda表达式,koinApplication对象是lambda表达式的接受者。

就是执行大括号内部的逻辑,在上面的例子就是执行:

  • KoinApplication.androidContext(this@MyApplication)
  • KoinApplication.modules(myAppModules)

koinApplication.createEagerInstances()做了什么?

结论:

  • 立刻创建Root Scope下在Module中声明了isCreatedAtStart = true的并且要保持单例的对象。

内部调用了Koin的createEagerInstances():

1
2
3
4
5
6
7
8
9
10
internal fun createEagerInstances() {  
createContextIfNeeded()
_scopeRegistry.rootScope.createEagerInstances()
}

internal fun createContextIfNeeded() {
if (_scopeRegistry._rootScope == null) {
_scopeRegistry.createRootScope()
}
}

ScopeRegistry.createRootScope()

刚开始_scopeRegistry._rootScope是为null的,所以会执行_scopeRegistry.createRootScope():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
internal fun createRootScope() {
if (_rootScope == null) {
_rootScope =
createScope(ScopeDefinition.ROOT_SCOPE_ID, ScopeDefinition.ROOT_SCOPE_QUALIFIER, null)
}
}

fun createScope(scopeId: ScopeID, qualifier: Qualifier, source: Any? = null): Scope {
if (scopes.contains(scopeId)) {
throw ScopeAlreadyCreatedException("Scope with id '$scopeId' is already created")
}

val scopeDefinition = scopeDefinitions[qualifier.value]
return if (scopeDefinition != null) {
val createdScope: Scope = createScope(scopeId, scopeDefinition, source)
_scopes[scopeId] = createdScope
createdScope
} else {
throw NoScopeDefFoundException("No Scope Definition found for qualifer '${qualifier.value}'")
}
}

private val _scopeDefinitions = HashMap<QualifierValue, ScopeDefinition>()
val scopeDefinitions: Map<QualifierValue, ScopeDefinition>
get() = _scopeDefinitions

private fun createScope(scopeId: ScopeID, scopeDefinition: ScopeDefinition, source: Any?): Scope {
val scope = Scope(scopeId, scopeDefinition, _koin, source)
val links = _rootScope?.let { listOf(it) } ?: emptyList()
scope.create(links)
return scope
}
  • 从ScopeRegistry的_scopeDefinitions这个Map中,取出之前创建过的Root ScopeDefinition对象。
  • 创建Scope对象,把ScopeDefinition对象通过Scope构造函数传入。
  • 调用scope.create(links)

links这里是做什么的暂时不管,因为不是主线。

Scope对象内部逻辑,之后再梳理,会比较连贯,这里先不具体分析。

Scope.createEagerInstances()

1
2
3
4
5
6
7
8
9
internal fun createEagerInstances() {
instances.values.filterIsInstance<SingleInstanceFactory<*>>()
.filter { instance -> instance.beanDefinition.options.isCreatedAtStart }
.forEach { instance ->
instance.get(
InstanceContext(_koin, _scope)
)
}
}

这段代码要到完全解析Scope源码的时候才能看懂。

简单的结论就是:
如果对象声明的时候标记了isCreatedAtStart = true,并且是要求单例,就创建它。

也就是说进可能早的去创建对象,而不是用到时延迟创建。

为什么会有这个需求?

因为可能需要在App启动时触发某些逻辑的运行。

Module

Module是如何创建和定义的?

参考官方示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
val appModule = module {
single<Service> { ServiceImpl() }
single<Service>(named("dumb")) { DumbServiceImpl() }

factory { RandomId() }
}

val mvpModule = module {
factory { (id: String) -> FactoryPresenter(id, get()) }

scope<MVPActivity> {
scoped { (id: String) -> ScopedPresenter(id, get()) }
}
}

val mvvmModule = module {
viewModel { (id: String) -> SimpleViewModel(id, get()) }

viewModel(named("vm1")) { (id: String) -> SimpleViewModel(id, get()) }
viewModel(named("vm2")) { (id: String) -> SimpleViewModel(id, get()) }


scope<MVVMActivity> {
scoped { Session() }
viewModel { ExtSimpleViewModel(get()) }
viewModel<ExtSimpleViewModel>(named("ext"))
}
}

val scopeModule = module {
scope(named(SCOPE_ID)) {
scoped(named(SCOPE_SESSION)) { Session() } onClose {
// onRelease, count it
Counter.released++
println("Scoped -SCOPE_SESSION- release = ${Counter.released}")
}
}
scope<ScopedActivityA> {
scoped { Session() }
scoped { SessionActivity(get()) }
}
}

val dynamicModule = module {
single { DynSingle() }
scope(named("dynamic_scope")) {
scoped { DynScoped() }
}
}

val javaModule = module {
scope<JavaActivity> {
scoped { Session() }
viewModel { CompatSimpleViewModel(get()) }
}
}

module{}是在做什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
typealias ModuleDeclaration = Module.() -> Unit

/**
* Define a Module
* @param createdAtStart
* @param override
*
* @author Arnaud Giuliani
*/
fun module(createdAtStart: Boolean = false, override: Boolean = false, moduleDeclaration: ModuleDeclaration): Module {
val module = Module(createdAtStart, override)
moduleDeclaration(module)
return module
}

创建了一个Module对象,然后执行moduleDeclaration函数,返回创建的Module对象。

moduleDeclaration函数也就是module{}大括号里的逻辑,大括号里的方法调用都委托给了Module对象。

所以分析module{}大括号里的逻辑,也就是主要分析Module中各个方法的逻辑。

从上面的示例中,可以看到调用的Module方法有:

  • factory
  • single
  • scope
  • viewModel

接下来一个个分析。

Module类定义

Module类定义代码很短,直接贴出来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/**
* Koin Module
* Gather/help compose Koin definitions
*
* @author Arnaud Giuliani
*/
class Module(
val createAtStart: Boolean,
val override: Boolean
) {
val rootScope: ScopeDefinition = ScopeDefinition.rootDefinition()
var isLoaded: Boolean = false
internal set
val otherScopes = arrayListOf<ScopeDefinition>()

/**
* Declare a group a scoped definition with a given scope qualifier
* @param qualifier
*/
fun scope(qualifier: Qualifier, scopeSet: ScopeDSL.() -> Unit) {
val scopeDefinition = ScopeDefinition(qualifier)
ScopeDSL(scopeDefinition).apply(scopeSet)
otherScopes.add(scopeDefinition)
}

/**
* Class Typed Scope
*/
inline fun <reified T> scope(scopeSet: ScopeDSL.() -> Unit) {
val scopeDefinition = ScopeDefinition(TypeQualifier(T::class))
ScopeDSL(scopeDefinition).apply(scopeSet)
otherScopes.add(scopeDefinition)
}

/**
* Declare a Single definition
* @param qualifier
* @param createdAtStart
* @param override
* @param definition - definition function
*/
inline fun <reified T> single(
qualifier: Qualifier? = null,
createdAtStart: Boolean = false,
override: Boolean = false,
noinline definition: Definition<T>
): BeanDefinition<T> {
return Definitions.saveSingle(
qualifier,
definition,
rootScope,
makeOptions(override, createdAtStart)
)
}

fun makeOptions(override: Boolean, createdAtStart: Boolean = false): Options =
Options(this.createAtStart || createdAtStart, this.override || override)

/**
* Declare a Factory definition
* @param qualifier
* @param override
* @param definition - definition function
*/
inline fun <reified T> factory(
qualifier: Qualifier? = null,
override: Boolean = false,
noinline definition: Definition<T>
): BeanDefinition<T> {
return Definitions.saveFactory(qualifier, definition, rootScope, makeOptions(override))
}

/**
* Help write list of Modules
*/
operator fun plus(module: Module) = listOf(this, module)

/**
* Help write list of Modules
*/
operator fun plus(modules: List<Module>) = listOf(this) + modules
}

/**
* Help write list of Modules
*/
operator fun List<Module>.plus(module: Module): List<Module> = this + listOf(module)

typealias Definition<T> = Scope.(DefinitionParameters) -> T

Module.factory()在做什么?

1
2
3
4
5
6
7
inline fun <reified T> factory(
qualifier: Qualifier? = null,
override: Boolean = false,
noinline definition: Definition<T>
): BeanDefinition<T> {
return Definitions.saveFactory(qualifier, definition, rootScope, makeOptions(override))
}

Definitions.saveFactory()源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
inline fun <reified T> saveFactory(
qualifier: Qualifier? = null,
noinline definition: Definition<T>,
scopeDefinition: ScopeDefinition,
options: Options
): BeanDefinition<T> {
val beanDefinition = createFactory(qualifier, definition, scopeDefinition, options)
scopeDefinition.save(beanDefinition)
return beanDefinition
}

inline fun <reified T> createFactory(
qualifier: Qualifier? = null,
noinline definition: Definition<T>,
scopeDefinition: ScopeDefinition,
options: Options,
secondaryTypes: List<KClass<*>> = emptyList()
): BeanDefinition<T> {
return BeanDefinition(
scopeDefinition,
T::class,
qualifier,
definition,
Kind.Factory,
options = options,
secondaryTypes = secondaryTypes
)
}

这里注意factory()最后一个参数definition是一个lambda表达式,代表创建对象的函数,执行这个函数,就会创建对象并获得它。

definition最终被存储到BeanDefinition中,名字很形象,这里把要注入的对象都叫做Bean。

接下来的关键逻辑在scopeDefinition.save(beanDefinition)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class ScopeDefinition(val qualifier: Qualifier, val isRoot: Boolean = false, private val _definitions: HashSet<BeanDefinition<*>> = hashSetOf()) {
val definitions: Set<BeanDefinition<*>>
get() = _definitions

fun save(beanDefinition: BeanDefinition<*>, forceOverride: Boolean = false) {
if (definitions.contains(beanDefinition)) {
if (beanDefinition.options.override || forceOverride) {
_definitions.remove(beanDefinition)
} else {
val current = definitions.firstOrNull { it == beanDefinition }
throw DefinitionOverrideException("Definition '$beanDefinition' try to override existing definition. Please use override option or check for definition '$current'")
}
}
_definitions.add(beanDefinition)
}
// ...
}

根据Module的源码,这里的scopeDefinition是rootScope,并且rootScope是在Module创建时一同创建的。

这里会有一个疑问,之前在Koin的ScopeRegistry里也创建了一个rootScope,root Scope有两个不同的实例,会不会有问题?看后面的逻辑就知道是没有问题的。

scopeDefinition.save(beanDefinition)做的就是把beanDefinition存储到到ScopeDefinition的Set类型属性中。

也就是说一个ScopeDefinition对应多个BeanDefinition。

Module.single()在做什么?

Module.single():

1
2
3
4
5
6
7
8
9
10
11
12
13
inline fun <reified T> single(
qualifier: Qualifier? = null,
createdAtStart: Boolean = false,
override: Boolean = false,
noinline definition: Definition<T>
): BeanDefinition<T> {
return Definitions.saveSingle(
qualifier,
definition,
rootScope,
makeOptions(override, createdAtStart)
)
}

Definitions.saveSingle():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
object Definitions {
inline fun <reified T> saveSingle(
qualifier: Qualifier? = null,
noinline definition: Definition<T>,
scopeDefinition: ScopeDefinition,
options: Options
): BeanDefinition<T> {
val beanDefinition = createSingle(qualifier, definition, scopeDefinition, options)
scopeDefinition.save(beanDefinition)
return beanDefinition
}

inline fun <reified T> createSingle(
qualifier: Qualifier? = null,
noinline definition: Definition<T>,
scopeDefinition: ScopeDefinition,
options: Options,
secondaryTypes: List<KClass<*>> = emptyList()
): BeanDefinition<T> {
return BeanDefinition(
scopeDefinition,
T::class,
qualifier,
definition,
Kind.Single,
options = options,
secondaryTypes = secondaryTypes
)
}
// ...
}

createSingle()与createFactory()创建BeanDefinition的区别在于,前者给BeanDefinition构造函数传的是Kind.Single,后者传的是Kind.Factory。

具体有什么用,得看使用BeanDefinition的地方。

scopeDefinition.save(beanDefinition)的过程与factory()是一样的,把beanDefinition存储在scopeDefinition的Set属性中。

Module.scope()在做什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* Declare a group a scoped definition with a given scope qualifier
* @param qualifier
*/
fun scope(qualifier: Qualifier, scopeSet: ScopeDSL.() -> Unit) {
val scopeDefinition = ScopeDefinition(qualifier)
ScopeDSL(scopeDefinition).apply(scopeSet)
otherScopes.add(scopeDefinition)
}

/**
* Class Typed Scope
*/
inline fun <reified T> scope(scopeSet: ScopeDSL.() -> Unit) {
val scopeDefinition = ScopeDefinition(TypeQualifier(T::class))
ScopeDSL(scopeDefinition).apply(scopeSet)
otherScopes.add(scopeDefinition)
}
  • 创建ScopeDefinition对象,传递ScopeDefinition的唯一标识。
  • 创建ScopeDSL对象,执行scopeSet这个lambda表达式,lambda表达式中可以不带前缀的调用ScopeDSL中的方法。
  • 新建的ScopeDefinition存储到Module的otherScopes这个list中。

ScopeDSL里有哪些方法可以调用?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
* DSL Scope Definition
*/
class ScopeDSL(val scopeDefinition: ScopeDefinition) {
@Deprecated("Can't use Single in a scope. Use Scoped instead", level = DeprecationLevel.ERROR)
inline fun <reified T> single(
qualifier: Qualifier? = null,
override: Boolean = false,
noinline definition: Definition<T>
): BeanDefinition<T> {
error("Scoped definition is deprecated and has been replaced with Single scope definitions")
}

inline fun <reified T> scoped(
qualifier: Qualifier? = null,
override: Boolean = false,
noinline definition: Definition<T>
): BeanDefinition<T> {
return Definitions.saveSingle(
qualifier,
definition,
scopeDefinition,
Options(isCreatedAtStart = false, override = override)
)
}

inline fun <reified T> factory(
qualifier: Qualifier? = null,
override: Boolean = false,
noinline definition: Definition<T>
): BeanDefinition<T> {
return Definitions.saveFactory(
qualifier,
definition,
scopeDefinition,
Options(isCreatedAtStart = false, override = override)
)
}
}

ScopeDSL里的scoped()方法跟Module.single()方法调用逻辑一样,factory()方法跟Module.factory()方法一样。

区别在于ScopeDSL中ScopeDefinition不是Root Scope,是刚才在Module.scope()里创建的ScopeDefinition。

Module.viewModel()在哪定义的?做了什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* ViewModel DSL Extension
* Allow to declare a ViewModel - be later inject into Activity/Fragment with dedicated injector
*
* @author Arnaud Giuliani
*
* @param qualifier - definition qualifier
* @param override - allow definition override
*/
inline fun <reified T : ViewModel> Module.viewModel(
qualifier: Qualifier? = null,
override: Boolean = false,
noinline definition: Definition<T>
): BeanDefinition<T> {
val beanDefinition = factory(qualifier, override, definition)
beanDefinition.setIsViewModel()
return beanDefinition
}

const val ATTRIBUTE_VIEW_MODEL = "isViewModel"

fun BeanDefinition<*>.setIsViewModel() {
properties[ATTRIBUTE_VIEW_MODEL] = true
}

fun BeanDefinition<*>.isViewModel(): Boolean {
return properties.getOrNull(ATTRIBUTE_VIEW_MODEL) ?: false
}

还是调用了factory()。

额外给BeanDefinition的properties加了一个isViewModel的属性,方便判断是不是ViewModel的BeanDefinition,其他没有什么影响。

Module总结

  • 在module中声明的对象不会立刻创建,创建对象的函数会当做BeanDefinition类型的变量存储在ScopeDefinition里Set属性中,以供需要时运行来创建对象。
  • scoped{}下声明的对象,存储在Module的otherScopes列表中。
  • 没有在scoped{}下声明的对象,存储在Module的rootScope中。

Koin怎么加载声明的Module的?

KoinApplication.modules()

在startKoin的lambda表达式里,通过调用KoinApplication.modules()加载指定的Module对象。

KoinApplication.modules()源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* Load definitions from modules
* @param modules
*/
fun modules(modules: List<Module>): KoinApplication {
if (koin._logger.isAt(Level.INFO)) {
val duration = measureDuration {
loadModules(modules)
}
val count = koin._scopeRegistry.size()
koin._logger.info("loaded $count definitions - $duration ms")
} else {
loadModules(modules)
}
if (koin._logger.isAt(Level.INFO)) {
val duration = measureDuration {
koin.createRootScope()
}
koin._logger.info("create context - $duration ms")
} else {
koin.createRootScope()
}
return this
}

private fun loadModules(modules: List<Module>) {
koin.loadModules(modules)
}

核心逻辑是koin.loadModules(modules)。

Koin.loadModules(modules)

1
2
3
4
5
6
7
8
9
10
class Koin {
val _modules = hashSetOf<Module>()

// ...

fun loadModules(modules: List<Module>) = synchronized(this) {
_modules.addAll(modules)
_scopeRegistry.loadModules(modules)
}
}

ScopeRegistry.loadModules(modules)

scopeRegistry.loadModules(modules)源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
internal fun loadModules(modules: Iterable<Module>) {
modules.forEach { module ->
if (!module.isLoaded) {
loadModule(module)
module.isLoaded = true
} else {
_koin._logger.error("module '$module' already loaded!")
}
}
}

private fun loadModule(module: Module) {
declareScope(module.rootScope)
declareScopes(module.otherScopes)
}

private fun declareScopes(list: List<ScopeDefinition>) {
list.forEach { scopeDefinition ->
declareScope(scopeDefinition)
}
}

每个Module中所有的ScopeDefinition都会调用declareScope()。

ScopeRegistry.declareScope(modules)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private val _scopeDefinitions = HashMap<QualifierValue, ScopeDefinition>()  
val scopeDefinitions: Map<QualifierValue, ScopeDefinition>
get() = _scopeDefinitions

private val _scopes = HashMap<ScopeID, Scope>()

private fun declareScope(scopeDefinition: ScopeDefinition) {
declareDefinitions(scopeDefinition)
declareInstances(scopeDefinition)
}

private fun declareInstances(scopeDefinition: ScopeDefinition) {
_scopes.values.filter { it._scopeDefinition == scopeDefinition }.forEach { it.loadDefinitions(scopeDefinition) }
}

private fun declareDefinitions(definition: ScopeDefinition) {
if (scopeDefinitions.contains(definition.qualifier.value)) {
mergeDefinitions(definition)
} else {
_scopeDefinitions[definition.qualifier.value] = definition.copy()
}
}

private fun mergeDefinitions(definition: ScopeDefinition) {
val existing = scopeDefinitions[definition.qualifier.value]
?: error("Scope definition '$definition' not found in $_scopeDefinitions")
definition.definitions.forEach {
existing.save(it)
}
}

ScopeRegistry.declareDefinitions()

declareDefinitions()做的是:

  • 如果发现ScopeRegistry的scopeDefinitions有Module中的ScopeDefinition,调用mergeDefinitions做两个ScopeDefinition的合并。
    • 怎么合并?就是把Module里的ScopeDefinition里的Set属性全部取出来,添加到ScopeRegistry中已存在的ScopeDefinition的Set属性中,Set属性存储的都是BeanDefinition。
  • 如果ScopeRegistry的scopeDefinitions没有Module中的ScopeDefinition,就直接存储到ScopeRegistry的_scopeDefinition哈希表中。

ScopeRegistry.declareInstances()

declareInstances()做的是:

  • 在ScopeRegistry的_scopes里寻找有没有Module中定义的Scope,有的话调用Scope的loadDefinitions()方法。

Scope.loadDefinitions()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
data class Scope(
val id: ScopeID,
val _scopeDefinition: ScopeDefinition,
val _koin: Koin,
val _source: Any? = null
) {
val _linkedScope: ArrayList<Scope> = arrayListOf()
val _instanceRegistry = InstanceRegistry(_koin, this)

//...

fun loadDefinitions(scopeDefinition: ScopeDefinition) {
scopeDefinition.definitions.forEach {
_instanceRegistry.createDefinition(it)
}
}
}

ScopeDefinition的definitions属性类型是Set<BeanDefinition<*>>

InstanceRegistry.createDefinition(BeanDefinition)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class InstanceRegistry(val _koin: Koin, val _scope: Scope) {
private val _instances = HashMap<IndexKey, InstanceFactory<*>>()
val instances: Map<IndexKey, InstanceFactory<*>>
get() = _instances

//...

internal fun createDefinition(definition: BeanDefinition<*>) {
saveDefinition(definition, false)
}

fun saveDefinition(definition: BeanDefinition<*>, override: Boolean) {
val defOverride = definition.options.override || override
val instanceFactory = createInstanceFactory(_koin, definition)
saveInstance(
indexKey(definition.primaryType, definition.qualifier),
instanceFactory,
defOverride
)
definition.secondaryTypes.forEach { clazz ->
if (defOverride) {
saveInstance(
indexKey(clazz, definition.qualifier),
instanceFactory,
defOverride
)
} else {
saveInstanceIfPossible(
indexKey(clazz, definition.qualifier),
instanceFactory
)
}
}
}

private fun createInstanceFactory(
_koin: Koin,
definition: BeanDefinition<*>
): InstanceFactory<*> {
return when (definition.kind) {
Kind.Single -> SingleInstanceFactory(_koin, definition)
Kind.Factory -> FactoryInstanceFactory(_koin, definition)
}
}

private fun saveInstance(key: IndexKey, factory: InstanceFactory<*>, override: Boolean) {
if (_instances.contains(key) && !override) {
error("InstanceRegistry already contains index '$key'")
} else {
_instances[key] = factory
}
}
}

这里做的主要是两件事:

  • 根据BeanDefinition的Kind属性,决定创建SingleInstanceFactory还是FactoryInstanceFactory。
    • 也就是说之前在module{}里配置时用到了factory{}就会创建FactoryInstanceFactory,用到single{}就会创建SingleInstanceFactory。
  • InstanceFactory对象保存在InstanceRegistry的_instances哈希表中。

InstanceRegistry是Scope的属性。

FactoryInstanceFactory是什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
* Factory Instance Holder
*
* @author Arnaud Giuliani
*/
class FactoryInstanceFactory<T>(koin: Koin, beanDefinition: BeanDefinition<T>) :
InstanceFactory<T>(koin, beanDefinition) {

override fun isCreated(): Boolean = false

override fun drop() {
beanDefinition.callbacks.onClose?.invoke(null)
}

override fun get(context: InstanceContext): T {
return create(context)
}
}

/**
* Koin Instance Holder
* create/get/release an instance of given definition
*/
abstract class InstanceFactory<T>(private val _koin: Koin, val beanDefinition: BeanDefinition<T>) {

/**
* Retrieve an instance
* @param context
* @return T
*/
abstract fun get(context: InstanceContext): T

/**
* Create an instance
* @param context
* @return T
*/
open fun create(context: InstanceContext): T {
if (_koin._logger.isAt(Level.DEBUG)) {
_koin._logger.debug("| create instance for $beanDefinition")
}
try {
val parameters: DefinitionParameters = context.parameters
return beanDefinition.definition.invoke(
context.scope,
parameters
)
} catch (e: Exception) {
val stack =
e.toString() + ERROR_SEPARATOR + e.stackTrace.takeWhile { !it.className.contains("sun.reflect") }
.joinToString(ERROR_SEPARATOR)
_koin._logger.error("Instance creation error : could not create instance for $beanDefinition: $stack")
throw InstanceCreationException("Could not create instance for $beanDefinition", e)
}
}

/**
* Is instance created
*/
abstract fun isCreated(): Boolean

/**
* Drop the instance
*/
abstract fun drop()

companion object {
const val ERROR_SEPARATOR = "\n\t"
}
}

InstanceFactory类核心就是create()方法,会调用BeanDefinition里definition属性函数来创建对象,并传递正确的参数。

FactoryInstanceFactory的核心是get()方法,get()是对外提供对象的,每次get()都会create()新的对象。

SingleInstanceFactory是什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
* Single instance holder
* @author Arnaud Giuliani
*/
class SingleInstanceFactory<T>(koin: Koin, beanDefinition: BeanDefinition<T>) :
InstanceFactory<T>(koin, beanDefinition) {

private var value: T? = null

override fun isCreated(): Boolean = (value != null)

override fun drop() {
beanDefinition.callbacks.onClose?.invoke(value)
value = null
}

override fun create(context: InstanceContext): T {
return synchronized(this) {
if (value == null) {
super.create(context)
} else value ?: error("Single instance created couldn't return value")
}
}

@Suppress("UNCHECKED_CAST")
override fun get(context: InstanceContext): T {
if (!isCreated()) {
value = create(context)
}
return value ?: error("Single instance created couldn't return value")
}
}
  • 第一次get()时,会create()新对象,并缓存在value属性中。
  • 后续get()都会读取缓存的value。

也就是说一旦get()过一次,对象就会一直保存在Scope对象里面,Scope对象就是管理要注入的对象的。

InstanceFactory.get()什么时候调用?

调用链:

Scope.get() -> Scope.resolveInstance() -> InstanceRegistry.resolveInstance() -> InstanceFactory.get()

加载Module总结

加载Module主要是做了:

  • 把module{}中声明的BeanDefinition全部复制到Koin里的ScopeRegistry里已有的ScopeDefinition里。这样不同地方的声明的对象创建过程就都汇总到同一个ScopeDefinition里了,可以集中式管理。
  • 如果module{}中声明的Scope对象已经存在,把InstanceFactory创建好,存储在Scope的_instanceRegistry的属性中的_instances哈希表属性中,Scope管理对象的创建。

怎么从Koin中获取注入的对象?

示例代码:

1
2
3
4
class HelloApplication : KoinComponent {
// Inject HelloService
val helloService by inject<HelloService>()
}

KoinComponent.inject():

1
2
3
4
5
inline fun <reified T> KoinComponent.inject(
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
): Lazy<T> =
lazy(LazyThreadSafetyMode.NONE) { getKoin().get<T>(qualifier, parameters) }

Koin.get():

1
2
3
4
inline fun <reified T> get(  
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
): T = _scopeRegistry.rootScope.get(qualifier, parameters)

最终还是调用了Root Scope的get()方法来获取对象。

Scope.get()做了什么?

调用链:
Scope.get() -> Scope.resolveInstance() -> InstanceRegistry.resolveInstance() -> InstanceFactory.get()

  • InstanceFactory如果是FactoryInstanceFactory,每次get()会创建新的对象。
  • InstanceFactory如果是SingleInstanceFactory,每次get()会获得同一个对象。

怎么获取特定的Scope?

在module里把对象声明在特定的Scope下。

那么想要获取Scope下的对象,就得调用Scope的get()方法。那么首先就得获得Scope对象。

可以通过Koin对象中的getOrCreateScope()来获取Scope。

内部实现:

1
2
3
4
5
6
7
8
9
10
11
12
// Koin.kt

fun getOrCreateScope(scopeId: ScopeID, qualifier: Qualifier): Scope {
return _scopeRegistry.getScopeOrNull(scopeId) ?: createScope(scopeId, qualifier)
}

fun createScope(scopeId: ScopeID, qualifier: Qualifier, source: Any? = null): Scope {
if (_logger.isAt(Level.DEBUG)) {
_logger.debug("!- create scope - id:'$scopeId' q:$qualifier")
}
return _scopeRegistry.createScope(scopeId, qualifier, source)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// ScopeRegistry.kt

typealias ScopeID = String

private val _scopes = HashMap<ScopeID, Scope>()

fun createScope(scopeId: ScopeID, qualifier: Qualifier, source: Any? = null): Scope {
if (scopes.contains(scopeId)) {
throw ScopeAlreadyCreatedException("Scope with id '$scopeId' is already created")
}

val scopeDefinition = scopeDefinitions[qualifier.value]
return if (scopeDefinition != null) {
val createdScope: Scope = createScope(scopeId, scopeDefinition, source)
_scopes[scopeId] = createdScope
createdScope
} else {
throw NoScopeDefFoundException("No Scope Definition found for qualifer '${qualifier.value}'")
}
}

private fun createScope(scopeId: ScopeID, scopeDefinition: ScopeDefinition, source: Any?): Scope {
val scope = Scope(scopeId, scopeDefinition, _koin, source)
val links = _rootScope?.let { listOf(it) } ?: emptyList()
scope.create(links)
return scope
}

Scope是怎么唯一标识的?

通过ScopeID唯一标识,ScopeID是String的别名。

因为ScopeRegistry的_scopes哈希表存储Scope是以ScopeID为Key。

qualifier是唯一标识ScopeDefinition的,两者不要搞混。

在Module.scope()声明scope时传的名字参数,传的也是qualifier,决定的是ScopeDefinition的唯一性。

module中可以有多个相同名称的scope声明

也就是说如果在module中定义多个qualifier一样的scope:

1
2
3
4
5
6
7
8
module {
scope(named("Hello")) {
factory { String("Luffy") }
}
scope(named("Hello")) {
factory { String("Luffy") }
}
}

根据上面的源码看,scope{}内部的BeanDefinition最终都是合并到同一个ScopeDefinition中的,也就是Koin里的ScopeRegistry里的存储ScopeDefinition的哈希表中的ScopeDefinition。

两个不同的Scope可以对应同一个ScopeDefinition

还可以发现,可以有两个不同的Scope,对应同一个ScopeDefinition,但实际内部对象创建还是两份的。

如何清空Scope里的对象?

为什么要清空呢?

比如有一个用户登录的作用域,不同用户登录,用户信息是不一样的,需要在用户注销后清空之前已创立的用户Scope。

调用Scope.close()即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Close all instances from this scope
*/
fun close() = synchronized(this) {
clear()
_koin._scopeRegistry.deleteScope(this)
}

internal fun clear() = synchronized(this) {
_closed = true
if (_koin._logger.isAt(Level.DEBUG)) {
_koin._logger.info("closing scope:'$id'")
}
// call on close from callbacks
_callbacks.forEach { it.onScopeClose(this) }
_callbacks.clear()

_instanceRegistry.close()
}

ScopeRegistry.deleteScope():

1
2
3
4
5
private val _scopes = HashMap<ScopeID, Scope>()

fun deleteScope(scope: Scope) {
_scopes.remove(scope.id)
}

把创建的Scope清除,因为Scope中缓存着创建的对象。

InstanceRegistry.close():

1
2
3
4
internal fun close() {  
_instances.values.forEach { it.drop() }
_instances.clear()
}

对于FactoryInstanceFactory的drop(),没做什么。

对于SingleInstanceFactory的drop(),会把缓存的value变量置为null。

Koin总结

Koin主要是围绕Scope构建的对象创建和存储体系,结构层次非常简洁清晰。

剩下未分析的特性,在上面的基本框架明确的情况下,稍微看看源码很容易就能懂,包括:

  • 启动时创建对象(createAtStart)
  • 定义覆盖(override)
  • secondaryTypes
  • properties
  • callback
  • android扩展包

参考资料