JSR-330 中的 Inject 和 Provider 有什么区别
What's the difference between Inject and Provider in JSR-330
全部
我不知道 JSR-330 中的 Inject 和 Provider 有什么区别。
我正在使用 google guice,每天都使用 @Inject
,而且我知道在 JSR-330 中,它有 Provider<T>
。
我的问题是
Provider<T>
是什么意思?
- 用户什么时候可以
Provider<T>
?
- 和
@Inject
有什么区别?
提前致谢。
一切都已经解释成javadoc,我引用:
Compared to injecting T
directly (implicitly using @Inject
only), injecting Provider<T>
enables:
- retrieving multiple instances.
- lazy or optional retrieval of an instance.
- breaking circular dependencies.
- abstracting scope so you can look up an instance in a smaller scope from an instance in a containing scope.
#1 示例:
这里你从同一个提供者那里得到了几个 Seat
的实例,所以它被用作一个工厂。
class Car {
@Inject
Car(Provider<Seat> seatProvider) {
Seat driver = seatProvider.get();
Seat passenger = seatProvider.get();
...
}
}
#2 示例:
这里你使用一个提供者来避免直接创建 class 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
来打破循环依赖,如下所示:
class C1 {
private final Provider<C2> c2;
@Inject
C1(Provider<C2> c2) {
this.c2 = c2;
...
}
}
这将允许容器首先完全创建 C1
的实例(因为我们实际上不需要创建 C2
的实例来注入 C2
的提供者) 一旦完成,容器将能够从 C1
.
的实例创建 C2
的实例
#4 示例:
这里你有一个 class 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();
...
}
}
全部
我不知道 JSR-330 中的 Inject 和 Provider 有什么区别。
我正在使用 google guice,每天都使用 @Inject
,而且我知道在 JSR-330 中,它有 Provider<T>
。
我的问题是
Provider<T>
是什么意思?- 用户什么时候可以
Provider<T>
? - 和
@Inject
有什么区别?
提前致谢。
一切都已经解释成javadoc,我引用:
Compared to injecting
T
directly (implicitly using@Inject
only), injectingProvider<T>
enables:
- retrieving multiple instances.
- lazy or optional retrieval of an instance.
- breaking circular dependencies.
- abstracting scope so you can look up an instance in a smaller scope from an instance in a containing scope.
#1 示例:
这里你从同一个提供者那里得到了几个 Seat
的实例,所以它被用作一个工厂。
class Car {
@Inject
Car(Provider<Seat> seatProvider) {
Seat driver = seatProvider.get();
Seat passenger = seatProvider.get();
...
}
}
#2 示例:
这里你使用一个提供者来避免直接创建 class 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
来打破循环依赖,如下所示:
class C1 {
private final Provider<C2> c2;
@Inject
C1(Provider<C2> c2) {
this.c2 = c2;
...
}
}
这将允许容器首先完全创建 C1
的实例(因为我们实际上不需要创建 C2
的实例来注入 C2
的提供者) 一旦完成,容器将能够从 C1
.
C2
的实例
#4 示例:
这里你有一个 class 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();
...
}
}