多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Koin 注解迁移指南:从 KSP 处理器迁移到 Koin Compiler Plugin

Koin 注解迁移指南:从 KSP 处理器迁移到 Koin Compiler Plugin 后端【免费下载链接】koinKoin - a pragmatic lightweight dependency injection framework for Kotlin Kotlin Multiplatform项目地址https://gitcode.com/gh_mirrors/ko/koin点击查看免费下载本文档面向正在使用koin-ksp-compilerKSP 处理器生成 Koin 注解代码的 Kotlin / Kotlin Multiplatform 项目系统讲解如何平滑迁移到新一代 Koin Compiler Plugin。迁移后你将获得更快的构建速度、编译期依赖校验、更简洁的 KMP 配置并且所有注解源码保持不变——真正需要改动的只有构建配置与 Koin 启动代码。迁移概览两种处理方式的本质差异Koin Annotations 的注解Singleton、Factory、Module等在 KSP 时代由独立的koin-ksp-compiler处理器在编译期扫描并生成 DSL 代码而在新方案中Koin Compiler Plugin 直接集成进 Kotlin K2 编译器FIR 分析 IR 变换不再产生任何可见的生成文件而是在编译过程中完成注解解析与依赖自动装配。两种方案的核心差异如下方面KSP 处理Compiler Plugin处理方式KSP独立步骤K2 编译器内建集成生成文件可见于build/generated/ksp无——内联变换构建速度较慢更快KMP 配置每个平台单独配置 KSP仅需应用一次插件Koin 启动modules(AppModule().module)startKoinMyApp()未来支持已弃用积极开发中好消息你的注解保持不变只有构建配置和 Koin 启动代码需要调整。koin-annotations库本身并未弃用它已并入主 Koin 项目并沿用主版本号弃用的只是 KSP 处理器本身详见 KSP 处理器设置已弃用。迁移前置要求Kotlin 2.3.20必须使用 K2 编译器编译器插件依赖 K2 的 FIR/IR 中间表示Gradle 8.x如果项目仍停留在 Kotlin 1.x则暂无法使用 Compiler Plugin只能继续使用 KSP 处理器过渡并尽快规划 Kotlin 升级。Step 1升级 Kotlin 版本Compiler Plugin 要求 Kotlin 2.3.20 及以上// build.gradle.kts plugins { kotlin(jvm) version 2.3.20 // 2.3.20 为最低版本 }对于多模块项目建议在根项目的build.gradle.kts或gradle/libs.versions.toml中统一声明 Kotlin 版本避免子模块间版本漂移。Step 2更新版本目录libs.versions.toml这是迁移中最直观的变化KSP 方案中koin-annotations与koin-ksp-compiler采用独立的koin-ksp版本号并与 KSP 插件版本耦合Compiler Plugin 方案中koin-annotations与koin-core使用同一个 Koin 版本KSP 插件则被完全移除。迁移前KSP[versions] koin 4.0.0 koin-ksp 2.0.0 # KSP 注解独立版本 ksp 2.0.0-1.0.22 [libraries] koin-core { module io.insert-koin:koin-core, version.ref koin } koin-annotations { module io.insert-koin:koin-annotations, version.ref koin-ksp } koin-ksp-compiler { module io.insert-koin:koin-ksp-compiler, version.ref koin-ksp } [plugins] ksp { id com.google.devtools.ksp, version.ref ksp }迁移后Compiler Plugin[versions] koin 4.2.0 koin-plugin 1.0.0 [libraries] koin-core { module io.insert-koin:koin-core, version.ref koin } koin-annotations { module io.insert-koin:koin-annotations, version.ref koin } [plugins] koin-compiler { id io.insert-koin.compiler.plugin, version.ref koin-plugin }koin-annotations现在是主 Koin 项目的一部分与koin-core使用相同版本不再存在注解库版本与核心库版本不一致的问题。Step 3更新构建配置build.gradle.kts移除 KSP 插件及其ksp(...)依赖配置改为应用io.insert-koin.compiler.plugin迁移前KSP// build.gradle.kts plugins { alias(libs.plugins.ksp) } dependencies { implementation(libs.koin.core) implementation(libs.koin.annotations) // KSP 版本独立版本号 ksp(libs.koin.ksp.compiler) } ksp { arg(KOIN_CONFIG_CHECK, true) }迁移后Compiler Plugin// build.gradle.kts plugins { alias(libs.plugins.koin.compiler) } dependencies { implementation(libs.koin.core) implementation(libs.koin.annotations) // 与 koin-core 同版本 } // 可选配置 koinCompiler { userLogs true // 输出组件检测日志 }需要注意KSP 时代的KOIN_CONFIG_CHECK编译期校验参数已被编译器插件的原生compileSafety能力取代默认开启不再需要手动传参。如果你使用了KoinViewModel或KoinWorker注解还需确保对应的运行时 DSL 依赖在 classpath 上如koin-core-viewmodel、koin-android-workmanager编译器插件会在缺少这些运行时库时直接报出明确错误而不是等到启动时抛出NoDefinitionFoundException。Step 4更新 Koin 启动代码核心代码变更这是迁移中唯一涉及源码改动的部分。KSP 方案依赖生成在build/generated/ksp中的.module扩展属性来组装模块Compiler Plugin 方案则通过KoinApplication注解配合类型化 API 完成启动不再需要任何生成代码导入。迁移前KSPimport org.koin.ksp.generated.* // 生成的扩展 Module ComponentScan(com.myapp) class AppModule fun main() { startKoin { modules(AppModule().module) // 生成的 .module 扩展 } }迁移后Compiler Plugin// 无需任何生成的导入 Module ComponentScan(com.myapp) class AppModule KoinApplication(modules [AppModule::class]) class MyApp fun main() { startKoinMyApp() // 类型化 API }其中KoinApplication注解定义于源码 CoreAnnotations.kt其签名为public annotation class KoinApplication(val configurations: ArrayString [], val modules : ArrayKClass* [Unit::class])——也就是说除了modules参数你还可以通过configurations指定要加载的配置标签详见下文配置标签一节。Android 应用示例迁移前KSPimport org.koin.ksp.generated.* class MyApplication : Application() { override fun onCreate() { super.onCreate() startKoin { androidContext(thisMyApplication) modules(AppModule().module) } } }迁移后Compiler PluginKoinApplication(modules [AppModule::class]) class MyApp class MyApplication : Application() { override fun onCreate() { super.onCreate() startKoinMyApp { androidContext(thisMyApplication) } } }可以看到androidContext(...)等配置块原样保留只是模块声明从生成扩展换成了类型化启动。Step 5清理并重建删除 KSP 生成的产物并全量重建rm -rf build/generated/ksp ./gradlew clean build如果 IDEAndroid Studio / IntelliJ仍报错或缓存异常建议同时执行 Invalidate Caches 并重启。注解保持不变所有已标注的类都无需任何改动// 无需修改 Singleton class UserRepository(private val database: Database) Factory class GetUserUseCase(private val repository: UserRepository) KoinViewModel class UserViewModel(private val useCase: GetUserUseCase) : ViewModel() Module ComponentScan(com.myapp) class AppModule所有注解的工作方式完全一致。完整注解清单可参考 注解定义参考。唯一导入变更KoinViewModelKoinViewModel注解的包路径发生了变化需要在源码中更新 import// 迁移前KSP import org.koin.android.annotation.KoinViewModel // 迁移后Compiler Plugin import org.koin.core.annotation.KoinViewModel这一点在源码中可以得到印证org.koin.core.annotation.KoinViewModel定义于 CoreAnnotations.ktTarget(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)支持binds参数而org.koin.android.annotation包中保留的则是 AndroidAnnotations.kt 里的KoinWorker。迁移时请务必将KoinViewModel的 import 指到org.koin.core.annotation。顶层函数定义新能力Compiler Plugin 支持在顶层函数上使用注解并通过ComponentScan自动发现。这对于无法直接标注的外部库实例数据库、缓存等特别有用函数返回值决定绑定类型函数参数自动作为依赖注入Singleton fun provideDatabase(): DatabaseService PostgresDatabase() Factory fun provideCache(db: DatabaseService): CacheService RedisCache(db) Module ComponentScan(com.myapp) class AppModule这种模式在 注解定义参考 中有更完整的示例如 Room、Ktor Client 等外部库的 provider 函数写法。DSL 语法变化如果你在注解模块之外还使用 Koin DSL 模块Compiler Plugin 引入了更简洁、编译期安全的 DSL 语法。核心区别在于新语法由插件自动检测构造参数无需手写get()调用或::Class引用KSP / 经典风格Compiler Plugin 风格singleOf(::MyService)singleMyService()factoryOf(::MyRepo)factoryMyRepo()viewModelOf(::MyVM)viewModelMyVM()scopedOf(::MyScoped)scopedMyScoped()workerOf(::MyWorker)workerMyWorker()single { fn(get()) }single { create(::fn) }// 迁移前 val myModule module { singleOf(::MyService) factoryOf(::MyRepository) viewModelOf(::MyViewModel) } // 迁移后 import org.koin.plugin.module.dsl.* val myModule module { singleMyService() factoryMyRepository() viewModelMyViewModel() } // 函数构建器——用于外部库Room、Retrofit 等 fun createDatabase(context: Context): AppDatabase Room.databaseBuilder(context, AppDatabase::class.java, db).build() val dbModule module { single { create(::createDatabase) } }Compiler Plugin DSL 位于org.koin.plugin.module.dsl包中经典 DSL 仍保留在org.koin.dsl包。两者可以共存经典 DSL 也继续受支持完整的插件 DSL 参考见 Compiler Plugin 设置 与 Koin Compiler Plugin 介绍。跨模块自动发现Configuration在大型多模块 Gradle 项目中可以使用Configuration实现跨 Gradle 模块的模块自动发现——feature 模块中的Module类无需在 app 模块显式列出// feature 模块中 Module ComponentScan Configuration class FeatureModule // app 模块中——FeatureModule 被自动发现 KoinApplication object MyApp startKoinMyApp() // FeatureModule 自动包含Configuration注解定义于 CoreAnnotations.kt支持vararg value: String配置标签用于按标签条件加载模块详见下文配置标签。多模块场景的完整示例库模块 app 模块如何分别应用插件可参考 Compiler Plugin 设置 的 Multi-Module Projects 一节。KMP 迁移从逐平台配置到单次应用Compiler Plugin 极大地简化了 Kotlin Multiplatform 的配置。KSP 方案需要为每个目标平台单独声明kspXxx配置Compiler Plugin 只需在plugins块中应用一次即可覆盖所有平台。迁移前KSP——逐平台配置// shared/build.gradle.kts plugins { kotlin(multiplatform) id(com.google.devtools.ksp) } kotlin { sourceSets { commonMain.dependencies { implementation(io.insert-koin:koin-core:$koin_version) implementation(io.insert-koin:koin-annotations:$koin_ksp_version) // 独立版本 } } } dependencies { // 每个平台都需要单独配置 KSP 编译器 add(kspAndroid, io.insert-koin:koin-ksp-compiler:$koin_ksp_version) add(kspIosX64, io.insert-koin:koin-ksp-compiler:$koin_ksp_version) add(kspIosArm64, io.insert-koin:koin-ksp-compiler:$koin_ksp_version) add(kspIosSimulatorArm64, io.insert-koin:koin-ksp-compiler:$koin_ksp_version) }迁移后Compiler Plugin——单插件应用// shared/build.gradle.kts plugins { kotlin(multiplatform) alias(libs.plugins.koin.compiler) } kotlin { sourceSets { commonMain.dependencies { implementation(libs.koin.core) implementation(libs.koin.annotations) } } }平台列表变化时如新增 target无需再手动追加 KSP 配置维护成本大幅下降。类型化启动 APICompiler Plugin 提供了一套类型化启动 API其中T为标注了KoinApplication的类API说明startKoinT()以应用类 T 全局启动 KoinstartKoinT { }以 T 启动并附带配置块koinApplicationT()创建隔离的 KoinApplicationkoinConfigurationT()从 T 创建 KoinConfiguration用于 Compose KoinApplication、Ktor 等场景此外moduleT()与modules(A::class, B::class)可以单独加载Module类无需KoinApplication在测试或混合注解/DSL 模块时非常实用。完整的 API 说明与示例见 使用注解启动 Koin。配置标签新能力Compiler Plugin 新增了配置标签Configuration Labels机制用于按标签条件加载模块。Configuration标注的模块只有在KoinApplication指定的configurations列表包含对应标签时才会被加载适合区分 prod / test 等不同运行环境// 仅 Configuration 默认标签的模块 Module Configuration class CoreModule // 仅 prod 标签的模块 Module Configuration(prod) class ProdModule // 仅 test 标签的模块 Module Configuration(test) class TestModule加载指定配置KoinApplication( modules [CoreModule::class], configurations [prod] // 只加载 Configuration(prod) 的模块 ) class ProdApp fun main() { startKoinProdApp() }Configuration注解支持vararg标签如Configuration(prod,test)也可与default组合使用更多细节见 注解模块参考。Compiler Plugin 配置选项在build.gradle.kts中通过koinCompiler { }配置块调整插件行为koinCompiler { userLogs true debugLogs false compileSafety true strictSafety true // 默认自动检测 skipDefaultValues true unsafeDslChecks true }各选项说明完整文档见 Compiler Plugin 选项选项说明默认值compileSafety编译期依赖校验A2/A3/A4 三级truestrictSafety强制聚合模块含startKoin/koinApplication/KoinApplication的模块每次构建重跑全图安全校验绕过 Kotlin 增量编译缓存聚合模块上自动开启skipDefaultValues跳过对带 Kotlin 默认值参数的注入改用默认值trueuserLogs输出组件检测与 DSL/注解处理日志falsedebugLogs输出插件内部处理的详细调试日志falseunsafeDslChecks校验 lambda 内的create()调用是否为唯一指令true开发期建议开启userLogs true可直观看到插件检测并处理了哪些组件便于排查注解未被检测类问题。编译期安全校验Compiler Plugin 的核心价值之一是编译期依赖验证——在构建期而非运行期发现缺失定义、限定符不匹配、调用点断裂等问题默认开启koinCompiler { compileSafety true // 默认开启 skipDefaultValues true // 默认开启 }校验分为三个层级模块级A2校验模块内定义对可见作用域的有效性、全图级A3在startKoinT()处校验完整装配图、调用点级A4校验每个getT()/injectT()调用。这意味着编译通过 依赖图成立替代了以往verify()/checkModules()的运行时测试手段。迁移期间如需临时绕过校验可将compileSafety置为false对无法在容器内解析的外部依赖可在参数上使用Provided跳过校验。详细机制见 编译期安全参考。排错指南移除 KSP 后构建失败执行./gradlew clean删除残留产物rm -rf build/generated/ksp使 IDE 缓存失效Invalidate Caches重新构建若为增量编译导致的误报安全错误如修改注解、移动包、改动ComponentScan后出现不应出现的编译错误先执行./gradlew clean build再判断——这是编译器插件与 Kotlin 增量编译的已知交互问题并非 Koin 特有。注解未被检测开启插件日志确认组件是否被扫描到koinCompiler { userLogs true }同时检查ComponentScan的包名是否正确支持精确包名与 glob 模式见 CoreAnnotations.kt 的注释说明。运行时缺少依赖检查ComponentScan的扫描包范围确认KoinApplication(modules [...])中列出的模块完整外部库实例使用Provided或顶层 provider 函数提供多模块项目编译期安全误报若插件报告缺少某个其实已存在于库模块的依赖需确认库模块也应用了 Koin Compiler Plugin它会生成下游模块读取的 hint 函数库模块先于消费模块构建implementation(project(:lib))通常由 Gradle 处理为库模块首次应用插件后执行一次 clean build。迁移检查清单升级 Kotlin 至 2.3.20升级 Koin 至 4.2.0移除 KSP 插件移除koin-ksp-compiler依赖将koin-annotations更新为主 Koin 版本io.insert-koin:koin-annotations:$koin_version添加 Koin Compiler Pluginio.insert-koin.compiler.plugin更新KoinViewModel的 import 至org.koin.core.annotation创建KoinApplication类将modules(X().module)替换为startKoinMyApp()若使用 DSL 模块将 import 更新为org.koin.plugin.module.dsl.*更新 DSL 语法singleOf(::X)→singleX()移除import org.koin.ksp.generated.*清理并重建rm -rf build/generated/ksp ./gradlew clean build延伸阅读Compiler Plugin 完整设置指南 —— 插件接入、多模块与 KMP 配置详解使用注解启动 Koin —— 类型化启动 API 与配置标签注解定义参考 —— 全部定义注解与 provider 函数模式Compiler Plugin 选项 —— 所有配置项及最佳实践编译期安全参考 —— A2/A3/A4 校验细节KSP 处理器设置已弃用 —— 遗留koin-ksp-compiler参考赞分享后端【免费下载链接】koinKoin - a pragmatic lightweight dependency injection framework for Kotlin Kotlin Multiplatform项目地址https://gitcode.com/gh_mirrors/ko/koin点击查看免费下载相关推荐Koin 注解的 KSP 处理器koin-ksp-compiler配置指南与 Compiler Plugin 迁移方案Koin 注解的 KSP 处理器koin ksp compiler配置指南与 Compiler Plugin 迁移方案 Koin Annotations 允后端从Hilt到Koin5步完成依赖注入框架轻量化迁移终极指南 从Hilt到Koin5步完成依赖注入框架轻量化迁移终极指南 在现代Android开发中依赖注入已成为构建可维护、可测试应用的核心技术。虽然Hilt作为后端Koin JSR-330 兼容实战指南用 Jakarta Inject 注解零改动迁移 Hilt / DaggerKoin JSR 330 兼容实战指南用 Jakarta Inject 注解零改动迁移 Hilt / Dagger Koin 通过 Koin Annotati后端上一篇碧蓝航线Alas自动化脚本7x24小时全自动游戏助手终极指南下一篇AzurLaneAutoScript碧蓝航线全自动脚本终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表