Java 如何让两个不同的@provider在Dagger 2中注入相同的@Singleton?

Java 如何让两个不同的@provider在Dagger 2中注入相同的@Singleton?,java,dependency-injection,dagger-2,dagger,Java,Dependency Injection,Dagger 2,Dagger,考虑到以下情况: public class SessionManager implements HasSession, HasCredentials{ /**implementation here*/ } 我已经定义了一个SessionModule,在请求注入HasSession或HasCredentials时注入SessionManager: @Module public abstract class SessionModule { @Provides @Singleton stat

考虑到以下情况:

public class SessionManager implements HasSession, HasCredentials{
/**implementation here*/
}
我已经定义了一个SessionModule,在请求注入HasSession或HasCredentials时注入SessionManager:

@Module
public abstract class SessionModule {
    @Provides @Singleton static HasSession hasSession(SessionManager sessionManager){
        return sessionManager;
    };

    @Provides @Singleton static HasCredentials hasCredentials(SessionManager sessionManager){
        return sessionManager;
    };
}
然后我定义了相应的组件:

@Component(modules={SessionModule.class})
@Singleton
public interface MyComponent {

    public HasSession getSessionProvider();

    public HasCredentials getCredentialsProvider();

}
getSessionProvider和getCredentialsProvider将创建/返回两个不同的SessionManager实例


我希望在调用getSessionProvider或getCredentialsProvider时创建并返回SessionManager的单个实例。我怎样才能用匕首2完成这项任务?

您需要做两件不同的事情:

  • 确定绑定的范围,以便只有一个实例
  • 将作用域绑定别名为备用类型
  • 首先,约束的范围:

    @Qualifier
    private @interface Scoped {}
    
    @Provides @Singleton
    @Scoped SessionManager scopeSessionManager(SessionManager manager) {
      return manager;
    }
    
    其次,别名作用域绑定:

    @Binds abstract HasSession bindHasSession(@Scoped SessionManager manager);
    @Binds abstract HasCredentials bindHasCredentials(@Scoped SessionManager manager);
    
    注意:这不会阻止此组件中的模块使用非作用域的会话管理器,因此请小心


    一种简单的解决方法是使用
    @Component.Builder
    并使用
    @BindsInstance
    传入一个有效范围的
    SessionManager
    实例(从而消除了对上面第一个代码段的需要,并允许您的原始代码工作).

    您需要做两件不同的事情:

  • 确定绑定的范围,以便只有一个实例
  • 将作用域绑定别名为备用类型
  • 首先,约束的范围:

    @Qualifier
    private @interface Scoped {}
    
    @Provides @Singleton
    @Scoped SessionManager scopeSessionManager(SessionManager manager) {
      return manager;
    }
    
    其次,别名作用域绑定:

    @Binds abstract HasSession bindHasSession(@Scoped SessionManager manager);
    @Binds abstract HasCredentials bindHasCredentials(@Scoped SessionManager manager);
    
    注意:这不会阻止此组件中的模块使用非作用域的会话管理器,因此请小心


    一种简单的解决方法是使用
    @Component.Builder
    并使用
    @BindsInstance
    传入一个有效范围的
    SessionManager
    实例(从而消除了对上面第一个代码段的需要,并允许您的原始代码工作).

    我找到了这个问题的解决方案:只需为SessionManager定义一个单例提供程序:

    @Provides @Singleton
    static SessionManager sessionManager(/*dependencies here*/){
        return new SessionManager(/**dependencies*/);
    }
    

    我找到了这个问题的解决方案:只需为SessionManager定义一个单例提供程序:

    @Provides @Singleton
    static SessionManager sessionManager(/*dependencies here*/){
        return new SessionManager(/**dependencies*/);
    }
    

    谢谢你的评论,杰克。我尝试了一下,但我想避免在不需要的时候使用绗缝机。如果我有两个相同接口的不同实现,我会选择它。我找到了一个非常简单的解决方案。谢谢你的评论,杰克。我尝试了一下,但我想避免在不需要的时候使用绗缝机。如果我有两个相同接口的不同实现,我会选择它。我找到了一个非常简单的解决方案。