我正在学习 Dagger。我是 Spring 的前用户。我注意到的一件事是我必须用
@IntoSet
注释每个 bean,才能将某种类型的 bean 作为集合注入。在 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
) 进行注释
为什么会发生这种情况,有解决方案/解决方法吗?
当您提供 @IntoSet 时,它只会在您的 Set 中。不能直接注入‘Jane’
如果您想专门注入 Jane,您可以为 Jane 提供命名注释或子类型,然后使用 @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 中的所有内容都是编译时生成的。所以这里没有猜测、投射或反思。它需要在编译时就全部清楚。