"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > Explorer les haricots synthétiques à Quarkus. Un mécanisme d’extension puissant

Explorer les haricots synthétiques à Quarkus. Un mécanisme d’extension puissant

Publié le 2024-09-02
Parcourir:879

Exploring Synthetic Beans in Quarkus. A Powerful Extension Mechanism

Dans le monde de Quarkus, le domaine de l'injection de dépendances est riche et polyvalent, offrant aux développeurs une multitude d'outils pour gérer et contrôler les beans. L’un de ces outils est le concept de haricots synthétiques. Les beans synthétiques sont un puissant mécanisme d'extension qui vous permet d'enregistrer des beans dont les attributs ne sont pas dérivés d'une classe, d'une méthode ou d'un champ Java. Au lieu de cela, tous les attributs d'un bean synthétique sont définis par une extension.

Dans cet article, nous allons plonger en profondeur dans le monde des haricots synthétiques dans Quarkus. Nous explorerons le besoin de haricots synthétiques, leurs applications pratiques et comment les créer et les utiliser dans vos applications Quarkus.

Comprendre les haricots synthétiques

Dans Quarkus, les beans sont les éléments constitutifs de votre application, gérés par le framework Contexts and Dependency Injection (CDI). En règle générale, les beans CDI sont des classes Java annotées avec diverses annotations CDI telles que @ApplicationScoped, @RequestScoped ou @Inject. Ces annotations
permettre à CDI de gérer automatiquement le cycle de vie et l'injection des beans.

Cependant, il existe des situations dans lesquelles vous devrez peut-être enregistrer un bean qui ne correspond pas parfaitement au modèle CDI traditionnel. C’est là que les haricots synthétiques entrent en jeu. Les beans synthétiques sont créés par des extensions et ont leurs attributs entièrement définis par ces extensions. Dans le monde du CDI classique, vous y parviendrez en utilisant les méthodes AfterBeanDiscovery.addBean() et SyntheticComponents.addBean(). Dans Quarkus, cela est accompli à l'aide de SyntheticBeanBuildItem.

Quand avez-vous besoin de haricots synthétiques ?

Alors, quand pourriez-vous avoir besoin d'utiliser des haricots synthétiques dans Quarkus ? Les haricots synthétiques sont un outil puissant lorsque :

  1. Intégration de bibliothèques tierces : Vous travaillez avec une bibliothèque tierce qui n'a pas d'annotations CDI mais doit être intégrée à votre application basée sur CDI. Les haricots synthétiques vous permettent de combler cet écart.

  2. Enregistrement dynamique des beans : Vous devez enregistrer les beans de manière dynamique au moment de l'exécution, en fonction de la configuration ou d'autres facteurs. Les beans synthétiques vous offrent la flexibilité de créer et d'enregistrer des beans à la volée.

  3. Gestion personnalisée des beans : Vous avez besoin d'un contrôle précis sur la portée et le comportement d'un bean qui ne peut pas être obtenu avec les annotations CDI standard.

  4. Implémentation de beans spécialisés : Vous souhaitez créer des beans spécialisés avec des attributs uniques qui ne correspondent pas aux classes ou méthodes Java traditionnelles.

  5. Dépendances moqueuses pour les tests : Les beans synthétiques fournissent un moyen utile de simuler les dépendances et d'injecter des implémentations fictives à des fins de test.

SynthesisFinishedBuildItem

Le SynthesisFinishedBuildItem est utilisé pour indiquer que le processus de découverte et d'enregistrement du bean CDI est terminé. Cela permet aux extensions de savoir quand il est possible d'interagir en toute sécurité avec les beans qui ont été enregistrés.

Par exemple:

@BuildStep  
void onSynthesisFinished(SynthesisFinishedBuildItem synthesisFinished){
    // CDI bean registration is complete, can now safely interact with beans
    }

SyntheticBeansRuntimeInitBuildItem

Le SyntheticBeansRuntimeInitBuildItem est utilisé pour enregistrer un rappel qui sera invoqué au moment de l'exécution une fois que tous les beans synthétiques ont été initialisés. Ceci est utile si vous devez exécuter une logique d'initialisation supplémentaire impliquant des beans synthétiques.

Par exemple:

@BuildStep
SyntheticBeansRuntimeInitBuildItem initSyntheticBeans(){

    return new SyntheticBeansRuntimeInitBuildItem(ids->{
    // Perform logic with initialized synthetic beans
    });

    }

Le rappel transmis à SyntheticBeansRuntimeInitBuildItem recevra un Set contenant les ID de tous les beans synthétiques initialisés.

En résumé, SynthesisFinishedBuildItem indique que la découverte du bean est terminée, tandis que SyntheticBeansRuntimeInitBuildItem permet d'initialiser la logique en fonction des beans synthétiques.

Création de haricots synthétiques avec SyntheticBeanBuildItem

Dans Quarkus, la création de beans synthétiques est un processus simple, grâce à la classe SyntheticBeanBuildItem. Passons en revue les étapes pour créer et utiliser un haricot synthétique :

  1. Créez la classe de haricots synthétiques : Commencez par définir la classe de haricots synthétiques. Ce cours sera la base de votre haricot synthétique.
package com.iqnev;

public class MySyntheticBean {

  // Define the behavior and attributes of your synthetic bean
  public void printMessage() {
    System.out.println("Hello from synthetic bean!");
  }
}
  1. Créez une extension Quarkus : Vous devrez créer une extension Quarkus pour enregistrer votre bean synthétique. Cette classe d'extension utilisera SyntheticBeanBuildItem pour configurer votre bean.

Approche de génération de bytecode

package com.iqnev;

import io.quarkus.arc.deployment.SyntheticBeanBuildItem;

public class MySyntheticBeanExtension {

  @BuildStep
  SyntheticBeanBuildItem syntheticBean() {
    return SyntheticBeanBuildItem
        .configure(MySyntheticBean.class)
        .scope(ApplicationScoped.class)
        .creator(mc -> {
          mc.returnValue(new MySyntheticBean());
        })
        .done();
  }
}

La méthode .creator() sur SyntheticBeanBuildItem est utilisée pour générer le bytecode qui créera des instances du bean synthétique au moment de l'exécution.

L'argument passé à .creator() est un Consumer qui permet de générer du bytecode Java à l'intérieur d'une méthode.

Dans cet exemple :

  1. mc est l'instance de MethodCreator
  2. mc.returnValue(new MySyntheticBean()) génère le bytecode pour créer une nouvelle instance de MySyntheticBean et la renvoie à partir de la méthode.

Donc, essentiellement, nous disons à Quarkus de générer une méthode qui ressemble à :

MySyntheticBean createSyntheticBean(){
    return new MySyntheticBean();
    }

Cette méthode générée sera ensuite appelée pour instancier le MySyntheticBean lorsqu'il devra être injecté ou utilisé.

La raison pour laquelle la génération de bytecode est utilisée est que les beans synthétiques ne correspondent pas aux classes/méthodes Java réelles, nous devons donc générer explicitement une méthode pour les instancier

La sortie de SyntheticBeanBuildItem est un bytecode enregistré au moment de la construction. Cela limite la manière dont les instances sont créées au moment de l'exécution. Les options courantes sont :

  1. Générer du bytecode directement via .creator()
  2. Utiliser une sous-classe BeanCreator
  3. Produire une instance via la méthode @Recorder

Approche enregistreur

Les approches @Record et .runtimeValue() sont des moyens alternatifs de fournir des instances de beans synthétiques dans Quarkus.

Cela vous permet d'instancier le bean synthétique via une méthode de classe enregistreur annotée avec @Record(STATIC_INIT).

Par exemple:

@Recorder
public class MyRecorder {

  @Record(STATIC_INIT)
  public MySyntheticBean createBean() {
    return new MySyntheticBean();
  }

}

  @BuildStep
  SyntheticBeanBuildItem syntheticBean(MyRecorder recorder) {
    return SyntheticBeanBuildItem
        .configure(MySyntheticBean.class)
        .runtimeValue(recorder.createBean());
  }

Ici, .runtimeValue() fait référence à la méthode enregistreur pour instancier le bean. Cela permet de transmettre directement une RuntimeValue pour fournir l'instance de bean synthétique.

Par exemple:

@BuildStep 
SyntheticBeanBuildItem syntheticBean(){

    RuntimeValue bean= //...

    return SyntheticBeanBuildItem
    .configure(MySyntheticBean.class)
    .runtimeValue(bean);

    }

La RuntimeValue peut provenir d'un enregistreur, d'un fournisseur, d'un proxy, etc.

Donc en résumé :

  • @Record est une approche pour générer la RuntimeValue
  • .runtimeValue() définit la RuntimeValue sur le SyntheticBeanBuildItem

Ils atteignent tous deux le même objectif : fournir une instance d'exécution, mais de manière légèrement différente.

Quand il s'agit de fournir des instances d'exécution pour les beans synthétiques dans Quarkus, j'envisagerais d'utiliser des enregistreurs (via @Record) comme une approche plus avancée par rapport à la génération directe de bytecode
avec .creator() ou en fournissant de simples RuntimeValues.

Voici quelques raisons pour lesquelles l'utilisation des enregistreurs peut être plus avancée :

  • Plus d'encapsulation - La logique pour instancier les beans est contenue dans une classe d'enregistreur distincte plutôt que directement dans les étapes de construction. Cela permet de simplifier les étapes de construction.
  • Réutilisation - Les méthodes d'enregistrement peuvent être réutilisées sur plusieurs beans synthétiques plutôt que de réécrire la logique du créateur.
  • Données d'exécution - Les méthodes Recorder s'exécutent au moment de l'exécution afin de pouvoir exploiter les ressources d'exécution, les configurations, les services, etc. pour construire des beans.
  • Injection de dépendances - Les méthodes d'enregistrement peuvent injecter d'autres services.
  • Contrôle du cycle de vie - Les méthodes d'enregistrement annotées avec @Record(STATIC_INIT) ou @Record(RUNTIME_INIT) donnent plus de contrôle sur le cycle de vie de l'instanciation du bean.
  • Beans gérés - Les beans instanciés dans les enregistreurs peuvent eux-mêmes être des beans gérés par CDI.

En résumé, les méthodes d'enregistrement offrent plus d'encapsulation, de flexibilité et d'accès aux données d'exécution et aux services pour instancier des beans synthétiques. Ils permettent une logique de production de beans plus avancée par rapport à la génération directe de bytecode.

Cependant, la génération directe de bytecode avec .creator() peut toujours être utile pour les cas simples où les enregistreurs peuvent être excessifs. Mais à mesure que les besoins en haricots synthétiques augmentent, les enregistreurs deviennent plus puissants et
approche avancée.

Il est possible de configurer un bean synthétique dans Quarkus pour qu'il soit initialisé pendant la phase RUNTIME_INIT au lieu de la phase STATIC_INIT par défaut.

Voici un exemple :

@BuildStep
@Record(RUNTIME_INIT)
SyntheticBeanBuildItem lazyBean(BeanRecorder recorder){

    return SyntheticBeanBuildItem
    .configure(MyLazyBean.class)
    .setRuntimeInit() // initialize during RUNTIME_INIT
    .runtimeValue(recorder.createLazyBean());

    }

Les points clés sont :

  • Utilisez setRuntimeInit() sur SyntheticBeanBuildItem pour le marquer pour RUNTIME_INIT
  • La méthode enregistreur doit être annotée avec @Record(RUNTIME_INIT)
  • Les beans synthétiques d'initialisation du runtime ne sont pas accessibles pendant STATIC_INIT

Donc, en résumé, les beans synthétiques peuvent être initialisés paresseusement pendant RUNTIME_INIT pour les cas où une instanciation hâtive de STATIC_INIT n'est pas nécessaire. Cela permet d'optimiser le temps de démarrage.

Utilisez le haricot synthétique : Maintenant que votre haricot synthétique est enregistré, vous pouvez l'injecter et l'utiliser dans votre application.

package com.iqnev;

import javax.inject.Inject;

public class MyBeanUser {

  @Inject
  MySyntheticBean mySyntheticBean;

  public void useSyntheticBean() {
    // Use the synthetic bean in your code
    mySyntheticBean.printMessage();
  }
}

Exécuter votre application : Créez et exécutez votre application Quarkus comme d'habitude, et le bean synthétique sera disponible pour l'injection et l'utilisation.

Conclusion

Les beans synthétiques dans Quarkus fournissent un mécanisme puissant pour intégrer des bibliothèques externes, enregistrer dynamiquement les beans et personnaliser le comportement des beans dans vos applications basées sur CDI. Ces beans, dont les attributs sont définis par des extensions plutôt que par des classes Java, offrent flexibilité et polyvalence dans la gestion des dépendances.

Comme nous l'avons exploré dans cet article, la création et l'utilisation de haricots synthétiques dans Quarkus sont un processus simple. En tirant parti des extensions SyntheticBeanBuildItem et Quarkus, vous pouvez combler de manière transparente le fossé entre le CDI traditionnel et les exigences d'enregistrement de beans plus spécialisées ou dynamiques.

Dans le paysage en constante évolution des frameworks Java, Quarkus continue de se démarquer en proposant des solutions innovantes telles que les beans synthétiques, ce qui en fait un choix incontournable pour le développement d'applications modernes, efficaces et flexibles. Profitez de la puissance des haricots synthétiques dans Quarkus et faites passer votre injection de dépendances au niveau supérieur !

Déclaration de sortie Cet article est reproduit sur : https://dev.to/yanev/exploring-synthetic-beans-in-quarkus-a-powerful-extension-mechanism-fbd?1 En cas de violation, veuillez contacter [email protected] pour le supprimer
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3