3

全部

我不知道 JSR-330 中的 Inject 和 Provider 有什么区别。我正在使用 google guice,并且每天都在使用@Inject,而且我知道在 JSR-330 中,它具有Provider<T>.

我的问题是

  1. 是什么意思Provider<T>
  2. 什么时候可以当用户Provider<T>
  3. 有什么区别@Inject

提前致谢。

4

1 回答 1

11

一切都已经在javadoc中进行了解释,我引用:

T直接注入 (仅隐式使用@Inject相比,注入Provider<T>能够:

  1. 检索多个实例。
  2. 实例的惰性或可选检索。
  3. 打破循环依赖。
  4. 抽象范围,以便您可以从包含范围内的实例中查找较小范围内的实例。

#1 的示例:

在这里,您从同一个提供者那里获得了几个实例,Seat因此它被用作工厂。

class Car {
    @Inject 
    Car(Provider<Seat> seatProvider) {
        Seat driver = seatProvider.get();
        Seat passenger = seatProvider.get();
        ...
    }
}

#2 的示例:

在这里,您使用提供程序来避免直接创建类的实例,MyClassLongToCreate因为我们知道这是一个缓慢的操作,因此我们将通过该get方法仅在需要时才懒惰地获取它。

class MyClass {
    @Inject
    private Provider<MyClassLongToCreate> lazy;
    ...
}

#3 的示例:

这是一个循环依赖,容器无法轻易解决,因此某些容器可能会抛出异常,因为它们不知道如何自己解决。

class C1 {
    private final C2 c2;
    @Inject
    C1(C2 c2) {
        this.c2 = c2;
        ...
    }
}

class C2 {
    private final C1 c1;
    @Inject
    C2(C1 c1) {
        this.c1 = c1;
        ...
    }
}

为了修复它,我们Provider在至少一个构造函数上使用 a 来打破循环依赖,如下所示:

class C1 {
    private final Provider<C2> c2;
    @Inject
    C1(Provider<C2> c2) {
        this.c2 = c2;
        ...
    }
}

这将允许容器完全创建C1first 的实例(因为我们实际上不需要创建实例C2来注入 的提供者C2)一旦完成,容器将能够C2C1.

#4 的示例:

在这里,您有一个C2作用域为会话的类,它依赖于C1它的作用域为请求,我们使用提供程序来允许我们获取与C1当前请求相对应的实例,因为它将从一个请求更改为另一个请求。

@RequestScoped
public class C1 {
    ...  
}

@SessionScoped
public class C2 {
    @Inject
    private Provider<C1> provider;
    ...
    public void doSomething() {
        // Get the instance corresponding to the current request
        C1 c1 = provider.get();
        ...
    }
}
于 2016-11-02T16:22:04.000 回答