JSR-330 兼容性
Koin 通过 Koin 注解和 Kotlin 编译器插件提供完整的 JSR-330 (Jakarta Inject) 兼容性。这使得 Koin 成为从 Hilt、Dagger 或其他 JSR-330 兼容框架迁移的团队的绝佳选择。
为什么选择 JSR-330?
JSR-330 为 Java/Kotlin 中的依赖项注入定义了一套标准注解:
| JSR-330 注解 | Koin 等效项 | 用途 |
|---|---|---|
@Inject | 构造函数检测 | 标记可注入的构造函数 |
@Singleton | @Single | 单例实例作用域 |
@Named | @Named | 基于字符串的限定符 |
@Qualifier | @Qualifier | 自定义限定符注解 |
@Scope | @Scope | 自定义作用域注解 |
设置
在您的项目中添加 koin-jsr330 依赖项:
kotlin
dependencies {
implementation("io.insert-koin:koin-jsr330:$koin_version")
}基本用法
@Singleton 和 @Inject
您现有的 Hilt/Dagger 类可以与 Koin 配合使用:
kotlin
import jakarta.inject.Inject
import jakarta.inject.Singleton
@Singleton
class UserRepository @Inject constructor(
private val api: ApiService,
private val database: UserDatabase
)
@Singleton
class ApiService @Inject constructor(
private val httpClient: OkHttpClient
)@Named 限定符
基于字符串的限定符工作方式完全相同:
kotlin
import jakarta.inject.Named
import jakarta.inject.Singleton
@Singleton
@Named("api")
class ApiOkHttpClient @Inject constructor() : OkHttpClient()
@Singleton
@Named("image")
class ImageOkHttpClient @Inject constructor() : OkHttpClient()
@Singleton
class NetworkManager @Inject constructor(
@Named("api") private val apiClient: OkHttpClient,
@Named("image") private val imageClient: OkHttpClient
)自定义 @Qualifier 注解
保留您现有的自定义限定符:
kotlin
import jakarta.inject.Qualifier
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class IoDispatcher
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class MainDispatcher
@Singleton
class CoroutineModule {
@IoDispatcher
fun provideIoDispatcher(): CoroutineDispatcher = Dispatchers.IO
@MainDispatcher
fun provideMainDispatcher(): CoroutineDispatcher = Dispatchers.Main
}
@Singleton
class DataSyncManager @Inject constructor(
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
)Android ViewModel
JSR-330 注解支持 Koin 的 ViewModel:
kotlin
import jakarta.inject.Inject
@KoinViewModel
class UserViewModel @Inject constructor(
private val userRepository: UserRepository,
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
fun loadUser(id: String) {
viewModelScope.launch {
val user = userRepository.getUser(id)
// ...
}
}
}NOTE
对于 ViewModel,请使用 @KoinViewModel (Koin 注解)。JSR-330 未定义 ViewModel 注解。
从 Hilt 迁移
之前 (Hilt)
kotlin
@HiltAndroidApp
class MyApplication : Application()
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject lateinit var analytics: Analytics
}
@Singleton
class Analytics @Inject constructor(
@ApplicationContext private val context: Context
)
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun provideRetrofit(): Retrofit = Retrofit.Builder()
.baseUrl("https://api.example.com")
.build()
}之后 (Koin 搭配 JSR-330)
kotlin
// Application - 使用 startKoin
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
startKoin {
androidContext(this@MyApplication)
modules(appModule)
}
}
}
// Activity - 使用 by inject()
class MainActivity : AppCompatActivity() {
private val analytics: Analytics by inject()
}
// 保持 @Singleton 和 @Inject 不变!
@Singleton
class Analytics @Inject constructor(
private val context: Context // Koin 自动提供 Context
)
// 使用 @Single 为提供的实例配置模块
@Module
@ComponentScan
class NetworkModule {
@Single
fun provideRetrofit(): Retrofit = Retrofit.Builder()
.baseUrl("https://api.example.com")
.build()
}混合使用
您可以在同一个项目中自由混合使用 JSR-330 和 Koin 注解:
kotlin
// JSR-330 风格
@Singleton
@Named("local")
class LocalDatabase @Inject constructor() : Database
// Koin 风格
@Single
@Named("remote")
class RemoteDatabase(private val api: ApiService) : Database
// 混合风格 - 带有 JSR-330 注入的 Koin 注解
@Factory
class DatabaseManager @Inject constructor(
@Named("local") private val local: Database,
@Named("remote") private val remote: Database
)编译器插件支持
Koin 编译器插件也能识别 JSR-330 注解:
kotlin
// 这些在编译器插件中是等效的
@Singleton
class UserRepository @Inject constructor(private val api: ApiService)
// 编译器插件 DSL (生成相同的代码)
val module = module {
single<UserRepository>()
}优势
- 零代码更改 - 现有的
@Inject和@Singleton注解可以直接使用 - 渐进式迁移 - 逐个模块进行迁移,混合使用 Hilt 和 Koin
- 符合标准 - JSR-330 是 Java/Kotlin 标准,并非特定于框架
- 团队熟悉度 - 开发者在 Hilt/Dagger 中已经熟悉了这些注解
- 工具链支持 - IDE 对 JSR-330 注解的支持
局限性
一些 Hilt 特有的功能没有直接的 JSR-330 等效项:
| Hilt 功能 | Koin 方案 |
|---|---|
@HiltAndroidApp | 在 Application 中使用 @KoinApplication + startKoin<T>{} |
@AndroidEntryPoint | by inject() 扩展函数 |
@HiltViewModel | @KoinViewModel |
@ApplicationContext | Context 参数 (自动注入) |
@ActivityContext | 基于作用域的上下文解析 |
