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()
}遷移後 (搭配 JSR-330 的 Koin)
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 | 基於作用域的 context 解析 |
