选项配置
选项配置(Options)是一种类型安全、统一、规范的应用程序配置方式,适用于多架构、多租户场景。它是依赖注入的重要扩展,帮助你将配置与业务逻辑解耦,提高代码的可维护性和使用的便利性。统一模块开发者和使用者之间的开发和使用习惯,简化模块上手的复杂度和可配置性。
快速启动
只需 5 步即可开始使用选项配置:
import spire_extensions_options.*
import spire_extensions_injection.*
// 1. 定义选项类型
public class ObsOptions {
public var accessKey = ""
public var accessSecret = ""
}
main() {
// 2. 创建服务集合
let services = ServiceCollection()
// 3. 注册选项配置
services.configure<ObsOptions>({ options =>
options.accessKey = "YWJjZGVmZ2hpamsxMjM0NTY3ODk"
options.accessSecret = "d0phbHJYVXRuRkVNSS9LN01ERU5HL2JQeFJmaUNZRVhBTVBMRUtFWQ=="
})
// 4. 构建服务提供者
let provider = services.build()
// 5. 解析并使用选项
let options = provider.getOrThrow<IOptions<ObsOptions>>()
options.value.accessKey |> println
options.value.accessSecret |> println
}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
提示
选项是单例的,使用configure方法配置选项会将配置函数和IOptions<T>,注册到容器中。首次解析选项时会使用配置函数来配置选项。
配置选项
选项模块扩展了依赖注入模块,并且提供了大量的配置函数。
注册选项
addOptions:注册选项
// 只注册,不配置
services.addOptions<ObsOptions>()2
此时可以从容器解析
IOptions<ObsOptions>
配置选项
configure:前置配置
// 注册,并配置
services.configure<ObsOptions>{options =>
options.accessKey = "xxx"
}
// 可以有多个配置方法
services.configure<ObsOptions>{options =>
options.accessKey = "YWJjZGVmZ2hpamsxMjM0NTY3ODk"
}2
3
4
5
6
7
8
9
同一个选项,可以有多个
configure,多个configure方法之间,按注册先后顺序执行。
configureAfter:后置配置
// 注册,并配置
services.configureAfter<ObsOptions>{options =>
options.accessKey = "xxxx"
}
// 可以多次配置
services.configure<ObsOptions>{options =>
options.accessKey = "YWJjZGVmZ2hpamsxMjM0NTY3ODk"
}2
3
4
5
6
7
8
9
configureAfter会在所有configure方法执行完成之后在执行。多个configureAfter之间按注册先后顺序执行
构建选项
OptionsBuilder:注册并配置选项
// 注册,并配置选项
services.addOptions<ObsOptions>()
.configure{ options =>
options.accessKey = "YWJjZGVmZ2hpamsxMjM0NTY3ODk"
}2
3
4
5
命名选项
let services = ServiceCollection()
// 租户1
services.configure<ObsOptions>("tenant1"){ options =>
options.accessKey = "QUtJQUlPU0ZPRE5ON0VYQU1QTEU"
}
// 租户2
services.configure<ObsOptions>("tenant2"){ options =>
options.accessKey = "YWJjZGVmZ2hpamsxMjM0NTY3ODk"
}
let provider = services.build()
let options = provider.getOrThrow<IOptionsMonitor<ObsOptions>>()
println(options.get("tenant1").accessKey)
println(options.get("tenant2").accessKey)2
3
4
5
6
7
8
9
10
11
12
13
命名选项在多租户场景下非常有用
configureAll:忽略名称前置配置
忽略名称配置所有同类型的选项
let services = ServiceCollection()
services.configure<ObsOptions>("tenant1"){ options =>
options.accessKey = "QUtJQUlPU0ZPRE5ON0VYQU1QTEU"
}
services.configure<ObsOptions>("tenant2"){ options =>
options.accessKey = "YWJjZGVmZ2hpamsxMjM0NTY3ODk"
}
// 忽略名称,配置所有的ObsOptions
services.configureAll<ObsOptions>{options =>
options.accessKey = "xxx"
}
let provider = services.build()
let options = provider.getOrThrow<IOptionsMonitor<ObsOptions>>()
println(options.get("tenant1").accessKey)
println(options.get("tenant2").accessKey)2
3
4
5
6
7
8
9
10
11
12
13
14
15
configureAll用于配置所有类型相同名称不同的选项,执行顺序同configure
configureAfterAll:忽略名称后置配置
let services = ServiceCollection()
services.configureAfterAll<ObsOptions>{options =>
options.accessKey = "xxx"
}
services.configure<ObsOptions>("tenant1"){ options =>
options.accessKey = "QUtJQUlPU0ZPRE5ON0VYQU1QTEU"
}
services.configure<ObsOptions>("tenant2"){ options =>
options.accessKey = "YWJjZGVmZ2hpamsxMjM0NTY3ODk"
}
let provider = services.build()
let options = provider.getOrThrow<IOptionsMonitor<ObsOptions>>()
println(options.get("tenant1").accessKey)
println(options.get("tenant2").accessKey)2
3
4
5
6
7
8
9
10
11
12
13
14
configureAfterAll用于配置所有同类型的选项,无论是否是命名选项,执行顺序同configureAfter
配置校验
解析时验证
配置完成后,可以调用 validate 方法对配置项进行校验,校验失败将会抛出异常
let services = ServiceCollection()
services.addOptions<ObsOptions>()
.configure{options =>
options.accessKey = "1234"
}
.validate("accessKey:长度必须大于5") { options =>
options.accessKey.size > 5
}
let provider = services.build()
let options = provider.getOrThrow<IOptions<ObsOptions>>()
// tip:选项验证必须是第一次访问时才会触发
options.value.accessKey |> println2
3
4
5
6
7
8
9
10
11
12
启动时验证
如果你希望在启动时验证某个选项,那么可以使用addOptionsWithValidateOnStart进行登记,启动时只需解析IStartupValidator来验证所有已登记的选项,这样就能在开发阶段规避错误。
let services = ServiceCollection()
services.addOptions<ObsOptions>()
.configure{options =>
options.accessKey = "123"
}
.validate("accessKey:长度必须大于5") { options =>
options.accessKey.size > 5
}
// 注册到IStartupValidator
services.addOptionsWithValidateOnStart<ObsOptions>()
let provider = services.build()
// IStartupValidator会检查所有已登记的选项
let validator = provider.getOrThrow<IStartupValidator>()
// 验证所有选项
validator.validate()2
3
4
5
6
7
8
9
10
11
12
13
14
15