【问题标题】:What's the difference between Inject and Provider in JSR-330JSR-330 中的 Inject 和 Provider 有什么区别
【发布时间】:2016-11-02 16:17:50
【问题描述】:

全部

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

我的问题是

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

提前致谢。

【问题讨论】:

    标签: java spring guice ioc-container jsr330


    【解决方案1】:

    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 来打破循环依赖:

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

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

    #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();
            ...
        }
    }
    

    【讨论】:

    • #2 - 慢不是唯一的原因,您可能还需要在实际需要时创建注入的对象,而不是在初始注入时创建。
    • @ThorbjørnRavnAndersen 如果#2,您的意思是“#2 的示例”,这只是一个示例,仅用于展示这个想法。您所描述的在我的回答中已经提到它是“可选检索”
    • 仅在引用中。
    • @ThorbjørnRavnAndersen 引用就是答案,其余的只是说明它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-25
    • 2011-08-18
    • 2021-06-12
    • 2021-10-17
    • 2012-08-28
    • 2020-01-09
    • 1970-01-01
    相关资源
    最近更新 更多