Veuillez expliquer l'annotation @produce dans CDI

j'ai lu sur le @produce annotation dans CDI, mais je ne comprends pas son usage.

public class Resources {

// Expose an entity manager using the resource producer pattern
@SuppressWarnings("unused")
@PersistenceContext
@Produces
private EntityManager em;                                        // 

@Produces
Logger getLogger(InjectionPoint ip) {                            // 
    String category = ip.getMember()
                        .getDeclaringClass()
                        .getName();
    return Logger.getLogger(category);
}

@Produces
FacesContext getFacesContext() {                                 // 
    return FacesContext.getCurrentInstance();
}

}

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

comment le conteneur sait-il appeler une méthode de producteur? Si J'injecte un EntityManager, comment le conteneur appelle-t-il le @ produces EntityManager? Et comment un getLogger producteur méthode appelée?

je ne vois pas la raison de passer par tous les ennuis.

38
demandé sur Luiggi Mendoza 2013-05-14 07:40:53

2 réponses

la Section 3.3 de l' spécification CDI donne un assez bon aperçu de haut niveau de l'utilisation de l' @Produces note:

une méthode productrice agit comme source d'objets à injecter, où:



• il n'est pas nécessaire que les objets à injecter soient des fèves, ou

• le type de béton des objets à injecter peut varier à l'exécution, ou

• objet exiger que certains d'initialisation personnalisée qui n'est pas exécutée par le bean constructeur.

disons, par exemple, que vous vouliez faire le pont entre un composant géré Java EE comme un gestionnaire d'entity et d'autres composants CDI, vous pourriez utiliser le @Produces annotation. Un autre avantage est que vous éviter d'avoir à dupliquer @PersistenceContext annotations 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 est de contourner les bibliothèques qui n'ont pas CDI amicale des haricots (par exemple, pas de constructeurs par défaut):

class SomeTPLClass {
    public SomeTPLClass(String 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 plus tard être injectée dans d'autres haricots gérés (très frais):

public class Shop { 
    @Produces @ApplicationScoped 
    @Catalog @Named("catalog") 
    private List<Product> products = new LinkedList<Product>(8);

    //...
}

public class OrderProcessor {
    @Inject
    @Catalog
    private List<Product> products;
}

le conteneur est responsable du traitement de toutes les méthodes et de tous les champs marqués d'un @produit l'annotation, et le fera normalement lorsque votre application est déployée. Les méthodes et les champs traités seront alors utilisé dans le cadre de la résolution du point d'injection pour les haricots gérés, selon les besoins.

62
répondu Perception 2013-05-14 06:55:58

l'exemple ne marchait pas tout à fait pour moi. Ce que dit le travail est un mineur de modifier:

@Alternative
class SomeTPLClass {
    public SomeTPLClass(String id) {
    }
}

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

donc j'ai dû ajouter @Alternative sur ma classe pour se débarrasser de l'erreur qu'il y avait deux options pour @Default.

0
répondu Hans 2017-11-07 14:48:22