Dagger中模块无作用域绑定覆盖构造函数注入单例绑定的原因探究
为什么Dagger选择了AppModule的无作用域绑定而非Foo的@Singleton构造注入?
这个现象本质是Dagger的绑定优先级规则在起作用,咱们来一步步拆解原因:
1. 显式@Provides方法优先级高于@Inject构造函数
Dagger在解析依赖实例的时候,有一套明确的绑定选择顺序,优先级从高到低是:
- 模块中显式定义的
@Provides(或@Binds)方法 - 类本身带有
@Inject注解的构造函数 - 通过
@BindsInstance提供的实例
你的代码里,AppModule中的provideFoo()是一个显式的@Provides绑定,所以Dagger会直接优先选用这个方法来创建Foo实例,完全跳过了Foo类本身带@Singleton的@Inject构造函数——这就是为什么生成的代码里没有用到DoubleCheck(Dagger实现单例的核心逻辑)。
2. 作用域注解的生效前提
Foo构造函数上的@Singleton注解,只有当Dagger通过这个构造函数来创建实例的时候才会生效。但因为模块的@Provides方法抢了优先级,Dagger根本不会去调用这个构造函数,自然也就不会应用单例的逻辑了。
3. 如何调整达到预期效果
如果你想让Foo以单例形式被提供,有两种方式:
- 删掉
AppModule中的provideFoo()方法,让Dagger使用Foo类的@Inject构造函数,此时@Singleton注解会生效,生成的代码会包含DoubleCheck逻辑 - 给
AppModule中的provideFoo()方法也加上@Singleton注解,这样Dagger会用这个方法创建单例实例,同样会生成单例相关的代码
附上你的示例代码:
@Module public class AppModule { @Provides public Foo provideFoo() { return new Foo(); } } @Component(module = AppModule.class) @Singleton public interface AppComponent { Foo getFoo(); } @Singleton class Foo @Inject constructor(){ //.. }
内容的提问来源于stack exchange,提问作者Saurabh
相关产品推荐
相关产品推荐

