java - 具有昂贵成员实例的 Guice Provider 是否应该使用 @Singleton 进行注释?

标签 java dependency-injection singleton guice

Guice Providers 应该用 @Singleton 注释吗?我的理由:如果 Provider 正在向其他 Singleton 类提供一个对象,并且对象本身的创建成本相对较高,那么使用在其 @Inject-标记的构造函数,将其存储为成员并仅在 getter 中返回已保存的全局变量?像这样:

@Singleton
public class MyProvider extends Provider<ExpensiveObject> {
    private ExpensiveObject obj;

    @Inject
    public MyProvider() {
        /* Create the expensive object here, set it to this.obj */
    }

    @Override
    public ExpensiveObject get() {
        return obj;
    }
}


更新

让我在这里再澄清一点。这与我是否应该使用 @Singleton.in(Singleton.class) 无关。这与创建对象的“缓存”有关。

假设对象创建需要多个 RPC 才能完成,例如反序列化 JSON 或发出 HTTP 请求。这可能需要相当长的时间。如果我要使用这个 Provider 多次注入(inject)类,那么只创建一次这样的对象不是很有意义吗?

另请注意,我必须能够使用 Provider,因为我需要能够注入(inject) Provider。

最佳答案

如果你的问题是你是否应该创建作用域提供者绑定(bind),或者你是否应该手动在你的提供者中缓存实例,那么真的,不要试图比 Guice 更聪明 :) 你真的不想做任何事情,只是在 get() 中创建昂贵的对象方法。简单测试用例:

public class MyProvider implements Provider<String> {
    public String get() {
        System.out.println("Called MyProvider.get()");
        return "abcd";
    }
}

public class MyModule extends AbstractModule {
    protected void configure() {
        bind(String.class).toProvider(MyProvider.class).in(Singleton.class);
    }
}

Injector injector = Guice.createInjector(new MyModule());
String abcd1 = injector.getInstance(String.class);  // Prints "Called MyProvider.get()
String abcd2 = injector.getInstance(String.class);  // Prints nothing!
// Or, if you want, comment out above two lines and try the following:
Provider<String> abcdProvider = injector.getProvider(String.class);
abcdProvider.get();  // Prints "Called MyProvider.get()"
abcdProvider.get();  // Prints nothing

你看,因为消息只打印了一次,MyProvider.get()方法也只被调用一次,正是因为 String绑定(bind)在单例范围内。

这里要理解的关键概念是提供者和绑定(bind)不是独立的实体。每个绑定(bind)都有一个关联的提供程序(当您使用 to() 创建普通绑定(bind)时,会为您创建一个隐式提供程序)。这可以很容易地从 getProvider() 中观察到。方法签名 - 它接受 Class<T>Key<T>对于您想要获得的实际类(class),而不是对于您绑定(bind)的提供者。当您创建到特定提供程序的绑定(bind)时,您不配置此提供程序,而是配置绑定(bind)。 Guice 足够聪明,即使您使用显式提供程序也可以考虑作用域,因此您不需要重新发明轮子并推出自己的单例。

如果您的问题具体是关于 @Singleton 的用法注释(与 bind() DSL 相反),那么我不知道它在提供者类中的存在是否会产生任何影响,但考虑到您应该使用 bind().toProvider()无论如何绑定(bind)到这个提供者,我认为这并不重要。只需使用 in()方法,肯定有用。

关于java - 具有昂贵成员实例的 Guice Provider 是否应该使用 @Singleton 进行注释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20473606/

相关文章:

java - 使用Java在FTP上按文件名删除文件

java - 将 ArrayList 对象声明为 final 以在常量文件中使用

azure - .net 7 隔离的 Azure 函数依赖注入(inject)在部署时失败(在本地工作)

coffeescript - 尝试开发 CoffeeScript Singleton Fetcher

java - 在 JSP 中使用 for 循环

java - 将 @ElementCollection 映射到同一个表

c# - 为什么以及如何仅在启动时使用 DI 容器?

c# - 使用插件覆盖 autofac 注册

java - Java 线程安全单例工厂

c# - 实例化时存在对象依赖,如何实现Singleton?