2017-09-22 6 views
0

Imaginez le modèle DI simplifié suivant:solution propre pour l'instanciation CDI désireux

@ApplicationScoped 
public class A { 

    private B b; 

    @Inject 
    public A(B b) { 
     this.B = b; 
    } 

} 

@ApplicationScoped 
public class B { 

    private C c; 

    @Inject 
    public B(C c) { 
     this.C = c; 
    } 

} 

@ApplicationScoped 
public class C { 

    @PostConstruct 
    public void start() { 
     // processing that should begin on startup 
    } 

} 

que je veuille C#start d'être appelé à la fin de déploiement. Le modèle qui est généralement suggéré en ligne est celui présenté here mais cette solution: 1) ajoute trop de passe-partout, 2) ajoute un nouveau fichier texte pour l'extension, 3) recourt à la triche d'utiliser toString uniquement pour déclencher le proxy B instancier la fève B réelle au-dessous qui, à son tour déclencher le proxy C etc.

Depuis CDI 1.1, en ajoutant la méthode suivante pour A est également une solution:

public void init(@Observes @Initialized(ApplicationScoped.class) Object init) { 
    B.toString(); 
} 

Cela résout les deux premiers problèmes décrits ci-dessus mais je dois encore appeler une méthode factice sur B de sorte que la chaîne d'instanciation/injection est déclenchée et finit par appeler la méthode annotée @PostConstruct de C. Est-ce qu'il me manque une solution plus propre à ce problème? CDI 2.0 répond-il à cela?

+0

Il se peut que je manque quelque chose, mais pourquoi ne pas simplement ajouter la classe '@Observes @ Initialized' à' C' pour forcer 'C' à démarrer. –

+0

C'est un bon point, mais idéalement je voudrais que l'instanciation des beans respecte la direction de la chaîne de dépendances. Avec votre solution, le bean C pourrait finir par être instancié sans aucune garantie que les beans A et B aient été instanciés. – papiomytoglou

+0

C'est un couplage étroit, qui est l'un des objectifs contre DI. –

Répondre

0

Il n'y a aucune option que vous pourriez choisir pour l'initialisation désirée, vous devez choisir une certaine "solution de contournement". CDI ne définit pas si bean init devrait être paresseux ou désireux et puisque la paresse a plus de sens la plupart du temps, Weld est allé de cette façon.

Votre meilleur pari est quelque chose de similaire à ce que le article you mentioned suggéré. Par exemple. mettre en place une extension, cerise choisir les haricots que vous voulez avoir initialisé avec empressement et les initialiser plus appeler une méthode (inoffensive) sur eux. De toute évidence, cela n'aura de sens que pour quelques beans dans votre déploiement (les applications sont limitées au maximum), de sorte qu'il n'y aura pas beaucoup de frais généraux, voire aucun. Il y a un peu de passe-partout, mais ce n'est pas comme si vous deviez écrire autant de lignes pour faire ce travail. Pour le rendre plus agréable, vous pouvez demander à tous vos beans d'implémenter une interface fictive avec la méthode ping() par défaut et appeler cette méthode à partir de l'extension - pour éviter d'appeler toString().

+0

Y a-t-il une raison de préférer la solution d'extension à la place du '@Observes @ Initialized 'que j'ai cité ci-dessus? – papiomytoglou

+0

Eh bien, l'extension ne crée pas de passe-partout sur vos haricots. Et c'est un endroit idéal pour résoudre ceci au lieu de le mettre à chaque grain où vous pourriez avoir besoin de ceci - ceci devrait ajouter à la maintenabilité. À part cela, je dirais qu'il n'y aura pas de différence majeure. – Siliarus