Veuillez expliquer l’annotation @Produces dans CDI

J’ai lu à propos de l’annotation @Produces dans CDI, mais je ne comprends pas son utilisation.

public class Resources { // Expose an entity manager using the resource producer pattern @SuppressWarnings("unused") @PersistenceContext @Produces private EntityManager em; // @Produces Logger getLogger(InjectionPoint ip) { // Ssortingng category = ip.getMember() .getDeclaringClass() .getName(); return Logger.getLogger(category); } @Produces FacesContext getFacesContext() { // return FacesContext.getCurrentInstance(); } 

}

extrait de: http://www.jboss.org/jdf/quickstarts/jboss-as-quickstart/guide/GreeterQuickstart/#GreeterQuickstart-

Comment le conteneur sait-il appeler une méthode de production? Si j’injecte un EntityManager, comment le conteneur appelle-t-il @Produces EntityManager? Et comment une méthode producteur getLogger serait appelée?

Je ne vois pas non plus la raison de traverser tous les problèmes.

La section 3.3 de la spécification CDI donne une bonne vue d’ensemble de l’utilisation de l’annotation @Produces :

Une méthode de production agit comme source d’objects à injecter, où:

• les objects à injecter ne doivent pas nécessairement être des haricots, ou
• le type de béton des objects à injecter peut varier au moment de l’exécution ou
• les objects nécessitent une initialisation personnalisée qui n’est pas effectuée par le constructeur du bean.

Supposons, par exemple, que vous souhaitiez @Produces un pont entre un composant géré Java EE tel qu’un gestionnaire d’entités et d’autres composants CDI, vous pourriez utiliser l’annotation @Produces . Un autre avantage est que vous évitez de dupliquer les annotations @PersistenceContext dans votre couche de domaine de données.

 class A { @PersistenceContext // This is a JPA annotation @Produces // This is a CDI 'hook' private EntityManager em; } class B { @Inject // Now we can inject an entity manager private EntityManager em; } 

Une autre utilisation pratique consiste à contourner les bibliothèques ne disposant pas de beans compatibles CDI (par exemple, aucun constructeur par défaut):

 class SomeTPLClass { public SomeTPLClass(Ssortingng id) { } } class SomeTPLClassProducer { @Produces public SomeTPLClass getInstance() { return new SomeTPLClass(""); } } 

Le Javadoc pour les produits montre également un cas intéressant (mais assez rare) de production d’une collection nommée qui peut ensuite être injectée dans d’autres beans gérés (très cool):

 public class Shop { @Produces @ApplicationScoped @Catalog @Named("catalog") private List products = new LinkedList(8); //... } public class OrderProcessor { @Inject @Catalog private List products; } 

Le conteneur est responsable du traitement de toutes les méthodes et de tous les champs marqués par une annotation @Produces et le fait normalement lorsque votre application est déployée. Les méthodes et champs traités seront ensuite utilisés dans le cadre de la résolution du point d’injection pour les haricots gérés, selon les besoins.

L’exemple n’a pas vraiment fonctionné pour moi. Ce que dit le travail était un tweak mineur:

 @Alternative class SomeTPLClass { public SomeTPLClass(Ssortingng id) { } } class SomeTPLClassProducer { @Produces public SomeTPLClass getInstance() { return new SomeTPLClass(""); } } 

J’ai donc dû append @Alternative à ma classe pour éliminer l’erreur qu’il y avait deux options pour @Default .