web-dev-qa-db-fra.com

Quand utiliser javax.inject.Provider au printemps?

Ce qu'il fait est assez simple:

@Inject
private Provider<ProductService> productService;

Le service Produit est disponible via productService.get() et .get() résoudra l'instance à partir du contexte Spring à chaque appel.

Mais quand dois-je l'utiliser? Et où?

Mon cas d'utilisation principal est assez simple: lorsque j'obtiens des dépendances circulaires, le fournisseur aide à résoudre la dépendance au moment de l'exécution. Mais cela semble un peu aléatoire si vous le lancez juste au moment où vous ne pouvez pas créer votre contexte provoqué par une dépendance circulaire.

Existe-t-il des modèles connus concernant l'utilisation des fournisseurs?

22
Tarion

Cette interface est équivalente à org.springframework.beans.factory.ObjectFactory<T> Qui est généralement utilisée pour éviter les appels à BeanFactory.getBean() dans le code client lors de la recherche d'instances de prototype. Souvent utilisé avec ObjectFactoryCreatingFactoryBean pour obtenir des beans prototypes provenant de BeanFactory.

exemple de 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>

Avec Providers, vous pouvez utiliser le ProviderCreatingFactoryBean à la place.

Une autre option pour résoudre le même problème (en utilisant l'héritage à la place de la composition) est la injection de méthode de recherche

20

Dans cdi, les fournisseurs sont utilisés pour injecter des objets de portée plus étroite dans un bean de portée plus large, par exemple, si un bean de portée de session a besoin d'accéder à un objet de portée de requête, il injecte un fournisseur, puis une méthode, qui s'exécute dans une demande , appelle provider.get() pour obtenir une référence de variable locale à l'objet de portée de requête approprié.

Compte tenu des éléments suivants:

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

Les éléments suivants utiliseront l'instance Bean1 associée à la première demande de la session pour utiliser Bean2 quelle que soit la demande qui appelle Bean2.doSomething ():

@SessionScoped
public class Bean2 {
    @Inject Bean1 bean;

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

Les éléments suivants utiliseront l'instance de Bean associée à la demande particulière qui appelle actuellement Bean3.doSomething (), c'est-à-dire un bean différent pour chaque demande:

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

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