← Назад к вопросам

Что такое Qualifier в Dagger?

1.8 Middle🔥 171 комментариев
#Dependency Injection#Архитектура и паттерны

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое Qualifier в Dagger

Qualifier в Dagger — это механизм аннотаций, позволяющий различать зависимости одного типа. По сути, это способ сказать Dagger: "Хотя у меня есть несколько объектов одинакового класса, я хочу инъектировать конкретный экземпляр, отмеченный специальной меткой". Это решает проблему, когда Dependency Injection (DI) фреймворк не может определить, какой именно экземпляр предоставить, если в графе зависимостей присутствует несколько объектов одного типа.

Проблематика без использования Qualifier

Рассмотрим классический пример. У нас есть два объекта типа String, которые должны использоваться в разных контекстах.

class UserRepository(
    private val apiUrl: String,
    private val dbName: String
)

Без Qualifier Dagger увидит два зависимости типа String и не сможет понять, какой String (URL API или имя базы данных) инъектировать в каждое поле. Он попытается найти одну @Provides-функцию, возвращающую String, что приведет к ошибке.

Решение с помощью Qualifier

Для решения создаются custom-аннотации, помеченные @Qualifier. Они служат уникальными "метками" для зависимостей.

1. Определение Qualifier-аннотаций

import javax.inject.Qualifier

@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class ApiUrl

@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class DatabaseName

2. Использование в модуле (Module)

В @Module мы создаем две отдельные функции предоставления, каждая помечена своей Qualifier-аннотацией.

@Module
class NetworkModule {
    @Provides
    @ApiUrl
    fun provideApiUrl(): String {
        return "https://api.example.com"
    }
}

@Module
class DatabaseModule {
    @Provides
    @DatabaseName
    fun provideDatabaseName(): String {
        return "app_database"
    }
}

3. Использование при инъекции (Inject)

В целевом классе мы аннотируем параметры конструктора соответствующими Qualifier-аннотациями.

class UserRepository @Inject constructor(
    @ApiUrl private val apiUrl: String,
    @DatabaseName private val dbName: String
) {
    fun fetchData() {
        println("Fetching from: $apiUrl")
        println("Using database: $dbName")
    }
}

Теперь Dagger четко понимает:

  • Для поля apiUrl нужно найти @Provides-метод, также помеченный @ApiUrl.
  • Для поля dbName — метод, помеченный @DatabaseName.

Альтернатива: @Named

Dagger также предоставляет стандартный Qualifier @Named, принимающий строковый параметр. Он удобен для простых случаев, но менее выразителен и может привести к ошибкам из-за повторения строк.

import javax.inject.Named

@Module
class AppModule {
    @Provides
    @Named("apiUrl")
    fun provideApiUrl(): String = "https://api.example.com"

    @Provides
    @Named("dbName")
    fun provideDatabaseName(): String = "app_database"
}

class UserRepository @Inject constructor(
    @Named("apiUrl") private val apiUrl: String,
    @Named("dbName") private val dbName: String
)

Ключевые преимущества использования Qualifier

  • Ясность и безопасность: Прямо указывается назначение зависимости, уменьшая путаницу.
  • Поддержка множественных экземпляров: Позволяет иметь несколько объектов одного типа в графе DI.
  • Улучшенная читаемость кода: Custom Qualifier с понятными названиями (@ApiUrl, @DefaultDispatcher, @IoDispatcher) делают код самодокументируемым.
  • Избегание конфликтов: Решает проблему, когда Dagger не может выбрать между несколькими кандидатами одного типа.

Практические примеры применения

Qualifier широко используются в реальных проектах:

  • Разные Retrofit клиенты для различных API (@MainApi, @AuthApi).
  • Coroutine Dispatchers (@MainDispatcher, @IoDispatcher, @DefaultDispatcher).
  • Конфигурационные строки или URL.
  • Разные реализации интерфейса (например, @MockDataSource и @RealDataSource для DataSource).

Вывод

Qualifier — это мощный и необходимый инструмент в Dagger, обеспечивающий точность и контроль в процессе инъекции зависимостей. Он превращает потенциальную ошибку неоднозначности в четко структурированную систему, где каждая зависимость получает уникальную идентификацию. Использование собственных (custom) Qualifier вместо @Named считается best practice, так как повышает читаемость и снижает вероятность ошибок.

Что такое Qualifier в Dagger? | PrepBro