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>

我的问题是

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

提前致谢。

一切都已经解释成javadoc,我引用:

Compared to injecting T directly (implicitly using @Inject only), injecting Provider<T> enables:

  1. retrieving multiple instances.
  2. lazy or optional retrieval of an instance.
  3. breaking circular dependencies.
  4. 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();
        ...
    }
}