Зависимость Dagger внедряется индивидуально и @IntoSet одновременно. Как мне это реализовать?

Я изучаю Даггер. Я бывший пользователь Spring. Одна из вещей, которую я заметил, это то, что мне нужно аннотировать каждый компонент с помощью @IntoSet, чтобы добавить компоненты определенного типа в коллекцию. В Spring я бы прямо объявил, например, Set<MyBeanClass> в качестве параметра в методе или конструкторе с автоматическим подключением, и фреймворк сам все выяснит (конечно, «фреймворк, который все сделает за вас», не всегда является преимуществом).

Однако @IntoSet иногда что-то ломает. Вот MRE:

package myown;

import dagger.Component;

import javax.inject.Named;
import javax.inject.Singleton;
import java.util.Set;

@Component(modules = {PersonModule.class})
@Singleton
public interface PersonComponent {
    Person getJane();
}
package myown;

import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoSet;

import javax.inject.Singleton;

@Module(includes = PetModule.class)
public class PersonModule {
    @IntoSet
    @Singleton
    @Provides
    public Person jane(Pet pet) {
        return new PetOwner("Jane", pet);
    }
}
package myown;

import dagger.Module;
import dagger.Provides;

import javax.inject.Singleton;

@Module
public class PetModule {
    @Provides
    @Singleton
    Pet getPet() {
        return new Pet("Puffy");
    }
}
package myown;

public class Person {
    private final String name;

    public Person(String name) {
        this.name = name;
    }
}
package myown;

public class PetOwner extends Person {
    private final Pet pet;

    public PetOwner(String name, Pet pet) {
        super(name);
        this.pet = pet;
    }
}
package myown;

public class Pet {
    private final String name;

    public Pet(String name) {
        this.name = name;
    }
}

Попробуйте построить его и вы получите:

java: [Dagger/MissingBinding] myown.Person cannot be provided without an @Inject constructor or an @Provides-annotated method.
      myown.Person is provided at
          myown.PersonComponent.getJane()

Однако если вы закомментируете @IntoSet и попытаетесь пересобрать, все будет в порядке.

Чтобы внести ясность, я хочу, чтобы jane можно было вводить непосредственно и как часть инъекции Set из всех Person (представьте, что есть jack, john и т. д., также помеченные @IntoSet)

Почему это происходит и есть ли решение/обходной путь?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
80
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Когда вы предоставляете @IntoSet, он будет только в вашем наборе. Вы не можете напрямую ввести «Джейн»

Если вы хотите внедрить Джейн конкретно, вы можете предоставить Джейн именованную аннотацию или подтип, а затем привязать или предоставить их снова с помощью @IntoSet.

@Module(includes = PetModule.class)
public class PersonModule {
    @Singleton
    @Provides
    @Named("Jane")
    public Person jane(Pet pet) {
        return new PetOwner("Jane", pet);

    @Provides
    @IntoSet
    public Person janeIntoSet(@Named("Jane") jane: Person) {
        return jane;
    }
}

Есть несколько способов добиться этого. См. https://dagger.dev/dev-guide/multibindings.html.

Разница в Spring заключается в том, что он определяет это во время выполнения, в то время как все в dagger генерируется во время компиляции. Так что здесь не происходит никаких догадок, кастингов или размышлений. Все должно быть ясно во время компиляции.

Спасибо! Я заметил, что Даггеру требуется @Named, даже если у меня есть только janejaneIntoSet, который тоже является Джейн). Person getJane() в интерфейсе @Component не будет работать, если я специально не упомяну, что разыскивается Джейн.

demavi 23.05.2024 07:52

Другие вопросы по теме