web-dev-qa-db-ja.com

Springでjavax.inject.Providerを使用する場合

それは非常に簡単です:

_@Inject
private Provider<ProductService> productService;
_

ProductサービスはproductService.get()を介して利用でき、.get()は呼び出しごとにSpringコンテキストからインスタンスを解決します。

しかし、いつそれを使用する必要がありますか?そしてどこに?

私の主な使用例は非常に単純です。循環依存関係を取得すると、プロバイダーは実行時に依存関係を解決するのに役立ちます。しかし、循環依存関係が原因でコンテキストを作成できない場合にスローすると、少しランダムに見えます。

プロバイダーの使用に関する既知のパターンはありますか?

22
Tarion

このインターフェイスは、プロトタイプインスタンスを探すときにクライアントコードでBeanFactory.getBean()呼び出しを回避するために通常使用されるorg.springframework.beans.factory.ObjectFactory<T>と同等です。 ObjectFactoryCreatingFactoryBeanをソースとするプロトタイプBeanを取得するためにBeanFactoryとともによく使用されます。

ObjectFactoryCreatingFactoryBean javadocsの例:

<beans>

   <!-- Prototype bean since we have state -->
   <bean id="myService" class="a.b.c.MyService" scope="prototype"/>

   <bean id="myServiceFactory"
       class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
     <property name="targetBeanName"><idref local="myService"/></property>
   </bean>

   <bean id="clientBean" class="a.b.c.MyClientBean">
     <property name="myServiceFactory" ref="myServiceFactory"/>
   </bean>

</beans>

Providersを使用すると、代わりにProviderCreatingFactoryBeanを使用できます。

同じ問題を解決する他のオプション(構成ではなく継承を使用)は、 lookup method injection です。

20

Cdiでは、プロバイダーはより狭いスコープのオブジェクトをより広いスコープのBeanに注入するために使用されます。たとえば、セッションスコープのBeanがリクエストスコープのオブジェクトへのアクセスを必要とする場合、プロバイダーとリクエストで実行されているメソッドを注入します、provider.get()を呼び出して、適切な要求スコープオブジェクトへのローカル変数参照を取得します。

次の場合:

@RequestScoped
public class Bean1 {
    void doSomething();
}

以下は、セッションの最初のリクエストに関連付けられたBean1インスタンスを使用して、どのリクエストがBean2.doSomething()を呼び出しているかに関係なく、Bean2を使用します。

@SessionScoped
public class Bean2 {
    @Inject Bean1 bean;

    public void doSomething() {
        bean.doSomething();
    }
}

以下は、現在Bean3.doSomething()を呼び出している特定のリクエストに関連付けられたBeanのインスタンス、つまりリクエストごとに異なるBeanを使用します。

@SessionScoped
public class Bean3 {
    @Inject Provider<Bean1> bean;

    public void doSomething() {
        bean.get().doSomething();
    }
}
24
rob