如何在Dagger 2中实现类似Micronaut的registerSingleton功能?
在Dagger 2中实现类似Micronaut的单例Bean注册
针对你用Micronaut的beanContext.registerSingleton(foo::class.java, myFooObject)注册单例Bean的场景,Dagger 2提供两种对应实现方式,分情况处理:
1. 让Dagger创建并管理单例(常规场景)
如果不需要传入已有的实例,而是让Dagger负责创建和维护单例:
- 若
Foo类通过构造函数注入,直接在类上标记@Singleton:@Singleton public class Foo { @Inject public Foo() {} } - 若需要通过Module提供实例,在
@Provides方法上添加@Singleton:@Module public class FooModule { @Provides @Singleton Foo provideFoo() { return new Foo(); } } - 最后确保Component接口标记
@Singleton作用域:
此时从同一个Component实例获取的@Singleton @Component(modules = FooModule.class) public interface AppComponent { Foo getFoo(); }Foo始终是同一个对象。
2. 注入已提前创建的外部实例(对应Micronaut的registerSingleton场景)
如果要把已实例化的myFooObject注册为Dagger管理的单例,有两种方式:
方式一:使用@BindsInstance绑定实例
通过Component的Builder接口传入外部实例:
@Singleton @Component public interface AppComponent { Foo getFoo(); @Component.Builder interface Builder { @BindsInstance Builder fooInstance(Foo foo); // 接收外部已创建的Foo实例 AppComponent build(); } }
创建Component时传入实例:
Foo myFooObject = new Foo(); // 提前创建好的实例 AppComponent component = DaggerAppComponent.builder() .fooInstance(myFooObject) .build();
方式二:通过Module传递外部实例
在Module中持有外部实例并提供:
@Module public class FooModule { private final Foo externalFoo; public FooModule(Foo externalFoo) { this.externalFoo = externalFoo; } @Provides @Singleton Foo provideFoo() { return externalFoo; } }
创建Component时传入Module:
Foo myFooObject = new Foo(); AppComponent component = DaggerAppComponent.builder() .fooModule(new FooModule(myFooObject)) .build();
关键注意点
Dagger的@Singleton作用域是绑定到Component实例的生命周期的,只有当Component本身是全局单例(整个应用只创建一次)时,对应的Bean才是全局单例,和Micronaut的全局单例行为一致。
内容的提问来源于stack exchange,提问作者Ehud Lev
相关产品推荐
相关产品推荐

