JSR-330との互換性
Koinは、Koin AnnotationsとKotlinコンパイラプラグインを通じて、JSR-330 (Jakarta Inject) との完全な互換性を提供します。これにより、KoinはHilt、Dagger、またはその他のJSR-330互換フレームワークから移行するチームにとって優れた選択肢となります。
なぜJSR-330なのか?
JSR-330は、Java/Kotlinにおける依存性注入(Dependency Injection)のための標準的なアノテーションセットを定義しています。
| JSR-330 アノテーション | Koinでの対応 | 目的 |
|---|---|---|
@Inject | コンストラクタ検出 | インジェクト可能なコンストラクタをマークする |
@Singleton | @Single | シングルインスタンスのスコープ |
@Named | @Named | 文字列ベースの修飾子(Qualifier) |
@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 修飾子
文字列ベースの修飾子(Qualifiers)も同様に動作します。
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 | @KoinApplication + Application内での startKoin<T>{} |
@AndroidEntryPoint | by inject() 拡張関数 |
@HiltViewModel | @KoinViewModel |
@ApplicationContext | Context パラメータ (自動インジェクト) |
@ActivityContext | スコープベースのコンテキスト解決 |
次のステップ
- Hilt 移行ガイド - 移行の完全なウォークスルー
- 修飾子 (Qualifiers) - Koinにおけるすべての修飾子オプション
- 定義 (Definitions) - JSR-330アノテーションの完全なリファレンス
