10
votes

Guice: Dois-je annoter chaque classe d'un graphique d'objet avec @Inject?

J'aimerais Introduisez Guice pour l'utilisation d'un projet de taille moyenne existant. Pour mes demandes, j'ai besoin d'une portée personnalisée (la session est trop grosse, tout en demandant à ma petite pour mon projet).

Imaginez que je Demande Guice pour me fournir une instance de la classe A qui a des dépendances directes et indirectes à de nombreuses autres classes (composition) .

Mon fournisseur personnalisé est capable de fournir l'instance de classes utilisées comme arguments de constructeur de toutes les classes impliquées.

question:

  • Dois-je vraiment mettre un @Inject (et ma portée personnalisée) sur les constructeurs de toutes les classes impliquées ou y a-t-il un moyen que Guice Ne nécessite que ces annotations sur la classe la classe supérieure que je demande et que toutes les dépendances supplémentaires sont résolues par "Demander" mon champ d'application personnalisé d'un fournisseur de types dépendants?

    / li>

    Si cela est vrai, cela augmenterait l'effort d'introduction de Guice car je dois ajuster plus de 1000 classes. Toute aide et expériences lors de l'introduction de Guice est appréciée.


2 commentaires

Vous trouverez peut-être Stackoverflow.com/questions/6123782/... intéressant


Notez que @Inject est également un JSR 330 Annotation , Ainsi, en utilisant elle ne coupe pas lui-même votre code à Guice.


3 Réponses :


0
votes

Au niveau le plus basique, le @Inject Annotation identifie la guice de choses devra être définie pour vous. Vous pouvez avoir une GUICE INJECT dans un champ directement, dans une méthode ou dans un constructeur. Vous devez utiliser l'annotation @Inject à chaque fois que vous souhaitez que GUICIC soit injecté un objet.

ici est un tutoriel de Guice.


3 commentaires

Donc, en d'autres termes, votre réponse de ma question est "Oui, je dois ajuster toutes les classes avec les deux annotations d'un graphique d'objet"? De mon point de vue, il s'agit d'une exigence inutile et augmente «la pollution d'annotation» et le coût de l'introduction de Guice.


Si vous utilisez un outil, vous devez utiliser l'outil. Il vous suffit d'utiliser Guice pour injecter ces objets que vous souhaitez injecter. Vous devez; Cependant, utilisez le @Inject pour injecter tous les objets que vous souhaitez injecter. Vous ne prenez pas un marteau et dites "" Dammit, pourquoi dois-je frapper les ongles de Darn, pourquoi le marteau ne peut-il pas le faire comme magiquement pour moi? " La même chose s'applique à Guice.


C'est vrai, mais je peux imaginer que Guice pourrait être suffisante intelligente pour travailler comme ce qui suit: 1. Vérifiez @Inject et obtenez une portée de la classe de niveau supérieur requis 2. S'il existe d'autres dépendances pour rechercher un @Inject Ou de demander la portée souhaitée de la classe de niveau supérieur pour un fournisseur de cette dépendance. Cela pourrait être mis en œuvre facilement à Guice et réduirait considérablement l'effort d'introduction.



14
votes

Tout d'abord, il est possible d'utiliser Guice sans mettre un @Inject annotation n'importe où. Guice prend en charge liaisons de fournisseur , @ fournit des méthodes et Liaisons de constructeur , qui vous permettent toutes de lier les types, mais vous choisissez. Toutefois, pour son fonctionnement normal, il nécessite @Inject annotations pour servir de métadonnées lui dire quelles dépendances nécessitent une classe et où il peut les injecter.

Cette raison en est que cela est que sinon, il ne peut pas déterminer de manière déterministe ce qu'il devrait injecter et où. Par exemple, les classes peuvent avoir plusieurs constructeurs et guice ont besoin d'une certaine manière de choisir celui de l'injection qui ne repose pas sur une devinette. Vous pourriez dire "Eh bien, mes classes ont un seul constructeur, il ne faut donc pas avoir besoin @Inject à ce sujet", mais que se passe-t-il lorsque quelqu'un ajoute un nouveau constructeur à une classe? Ensuite, Guice n'a plus sa base pour décider et la candidature se casse. De plus, tout cela suppose que vous ne faites que faire une injection de constructeur. Tandis que l'injection du constructeur est certainement le meilleur choix en général, Guice permet également une injection de méthodes (et de champs) également, et le problème de nécessiter de spécifier les points d'injection d'une classe explicite explicitement, car la plupart des classes auront de nombreuses méthodes qui ne sont pas utilisé pour l'injection et au plus quelques-uns qui sont.

En plus de @Inject d'une importance en disant Guice, elle sert également de documentation sur la manière dont une classe est destinée à être utilisée - que la classe fait partie de l'infrastructure câblée d'une dépendance de la demande d'application . Il est également utile d'être cohérents dans l'application de @Inject annotations sur vos classes, même si ce ne serait pas absolument nécessaire sur certains qui utilisent simplement un seul constructeur. Je noterais également que vous pouvez utiliser JSR-330's @javax. INJECT.Inject Annotation à Guice 3.0 Si une annotation Java standard est préférable à une guice spécifique une à vous.

Je ne suis pas trop clair sur ce que vous entendez en demandant à la portée d'un fournisseur. Les scopes ne créent généralement pas d'objets eux-mêmes; Ils contrôlent quand demander au fournisseur non calculé d'une dépendance pour une nouvelle instance et comment contrôler la portée de cette instance. Bien sûr, les fournisseurs font partie de leur fonctionnement, mais je ne sais pas si c'est ce que vous voulez dire. Si vous avez un moyen personnalisé de fournir des instances d'objets, fournisseur liants et @provides est le moyen d'aller pour cela et ne nécessite pas @Inject < / code> annotations sur les classes elles-mêmes.


4 commentaires

Réponse complète, merci. Question additionnelle: Qu'en est-il des classes / interfaces 3ème partie (par exemple Javax.persistence.entityManager) - Les trois méthodes que vous avez décrites semblent être scorrent - et si une telle classe de 3ème partie doit être récupérée dans une étendue (personnalisée)? Je sais comment récupérer l'instance correcte, mais malheureusement, la méthode de la portée () n'est jamais appelée des cours sans @Inject. (C'est ce que je voulais dire avec "demander" ma portée personnalisée)


Bonne réponse. La plupart des gens ont tendance à penser que Guice, parce que c'est une annotation basée sur une annotation, est un cadre invasif, mais il n'est pas nécessaire.


Et si vous voulez éloigner de Guice à un autre fournisseur DI, vous êtes laissé avec @Inject () partout


@skjagini @Inject est maintenant une annotation Java standard ( javax.inject.inject ) qui fonctionne avec la plupart des frameworks Java di.



1
votes

Non, vous ne

Guice ne vous demande pas d'injecter chaque objet. Guice va essayer de créer uniquement des objets injectés. Donc, vous pouvez @Iser des objets que vous souhaitez injecter. P>

sur le bit d'application - Scope contrôle essentiellement comment vos objets sont créés par GUICE. Lorsque vous écrivez votre propre portée personnalisée, vous pouvez avoir une source de données qui contrôlent la manière dont les objets sont créés. Lorsque vous avez portée une classe avec votre annotation personnalisée, Guice appellera votre méthode d'étendue avant la création avec un fournisseur pour cette classe. Vous pouvez ensuite décider si vous souhaitez créer un nouvel objet ou utiliser un objet existant à partir d'une DataStructure (telle que HASHMAP ou quelque chose). Si vous souhaitez utiliser un existant, vous obtenez cela et renvoyez l'objet, sinon vous faites un fournisseur.get () et retour. P>

Notez ce P>

public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
    return new Provider<T>() {
      public T get() {
        Map<Key<?>, Object> scopedObjects = getScopedObjectMap(key);

        @SuppressWarnings("unchecked")
        T current = (T) scopedObjects.get(key);
        if (current == null && !scopedObjects.containsKey(key)) {
          current = unscoped.get();
          scopedObjects.put(key, current);
        }
        // what you return here is going to be injected ....
        // in this scope object you can have a datastructure that holds all references 
        // and choose to return that instead depending on your logic and external 
        // dependencies such as session variable etc...
        return current;
      }
    };
  }


1 commentaires

Merci pour la réponse, mais la question était si je dois placer l'annotation @Inject sur chaque classe du graphique d'objet. Je ne demande pas à instantifier toutes ces classes.