在unice中懒惰加载非单例

时间:2017-11-29 10:37:35

标签: java dependency-injection guice provider

我在我的项目中使用Guice for DI,我希望在我的类中对非单例对象进行延迟初始化。 我试图使用Provider,但每次调用get()方法时它都返回了新实例。

public class MyClass {
  @Inject
  private Provider<Service> serviceProvider; //Service is NOT Singleton

  public void meth1() {
    Service s1 = serviceProvider.get();       
  }

  public void meth2() {
    Service s2 = serviceProvider.get();
  }
  //I want  s1 and s2 to be the same object
}

Guice可以做到这一点,还是有任何其他做法可以实现这一目标?

2 个答案:

答案 0 :(得分:1)

如果您需要s1s2来引用相同的实例,那么您只需要Service的单个实例来实现MyClass的实例,并且只需解析到实例字段

public class MyClass {

  @Inject
  private Provider<Service> serviceProvider;

  private Service service;

  public void meth1() {
    if (this.service == null) this.service = this.serviceProvider.get();
    // use service 
  }

  public void meth2() {
    if (this.service == null) this.service = this.serviceProvider.get();
    // use service 
  }
}

答案 1 :(得分:1)

正如塔维安在评论中提到的,最好的解决方案是Suppliers.memoize(serviceProvider::get),或者是等价的。 Suppliers(和Supplier)位于Google实用程序库Guava中,自Java 8起,Guava的供应商扩展了Java 8功能接口Supplier,尽管Java 8不支持供应供应商等效的内置。 serviceProvider::get的规范对于使提供者在没有显式适配器的情况下作为供应商行为是必要的,即使他们都指定了一个方法,零范围T get()

与Google的其他DI框架Dagger不同,供应商没有Lazy类来提供您正在寻找的本地备忘录。虽然您可以执行tmarwen在their updated answer中提供的那种“检查然后设置”行为,但该策略(如其评论中所述)不是线程安全的,而Suppliers.memoize显然是线程安全的。

虽然Guava提供了许多有用的功能,但您可能不希望为单个方法添加全新的库。如果确实需要没有完整库的线程安全性,可以查看the Apache-licensed implementation here