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 haricot synthétique sont définis par une extension.
Dans cet article, nous allons plonger en profondeur dans le monde des haricots synthétiques chez Quarkus. Nous explorerons le besoin de haricots synthétiques, leurs applications pratiques et comment les créer et les utiliser dans vos applications Quarkus.
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 rentre pas parfaitement dans le 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 en utilisant SyntheticBeanBuildItem.
Alors, quand pourriez-vous avoir besoin d'utiliser des haricots synthétiques dans Quarkus ? Les haricots synthétiques sont un outil puissant lorsque :
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.
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 haricots synthétiques vous offrent la flexibilité nécessaire pour créer et enregistrer des haricots à la volée.
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.
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.
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 simulées à des fins de test.
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 sûr d'interagir 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 }
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 effectuer 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
Donc, 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.
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 :
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!"); } }
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
Dans cet exemple :
So essentially, we are telling Quarkus to generate a method that looks something like:
MySyntheticBean createSyntheticBean(){ return new MySyntheticBean(); }
This generated method will then be called to instantiate the MySyntheticBean when it needs to be injected or used.
The reason bytecode generation is used is that synthetic beans do not correspond to real Java classes/methods, so we have to explicitly generate a method to instantiate them
The output of SyntheticBeanBuildItem is bytecode recorded at build time. This limits how instances are created at runtime. Common options are:
The @Record and .runtimeValue() approaches are alternate ways of providing instances for synthetic beans in Quarkus.
This allows you to instantiate the synthetic bean via a recorder class method annotated with @Record(STATIC_INIT).
For example:
@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()); }
Here the .runtimeValue() references the recorder method to instantiate the bean. This allows passing a RuntimeValue directly to provide the synthetic bean instance.
For example:
@BuildStep SyntheticBeanBuildItem syntheticBean(){ RuntimeValue<MySyntheticBean> bean= //... return SyntheticBeanBuildItem .configure(MySyntheticBean.class) .runtimeValue(bean); }
The RuntimeValue could come from a recorder, supplier, proxy etc.
So in summary:
They both achieve the same goal of providing a runtime instance, just in slightly different ways.
When it comes to providing runtime instances for synthetic beans in Quarkus, I would consider using recorders (via @Record) to be a more advanced approach compared to directly generating bytecode
with .creator() or supplying simple RuntimeValues.
Here are some reasons why using recorders can be more advanced:
So in summary, recorder methods provide more encapsulation, flexibility and access to runtime data and services for instantiating synthetic beans. They allow for more advanced bean production logic compared to direct bytecode generation.
However, direct bytecode generation with .creator() can still be useful for simple cases where recorders may be overkill. But as synthetic bean needs grow, recorders are a more powerful and
advanced approach.
It is possible to configure a synthetic bean in Quarkus to be initialized during the RUNTIME_INIT phase instead of the default STATIC_INIT phase.
Here is an example:
@BuildStep @Record(RUNTIME_INIT) SyntheticBeanBuildItem lazyBean(BeanRecorder recorder){ return SyntheticBeanBuildItem .configure(MyLazyBean.class) .setRuntimeInit() // initialize during RUNTIME_INIT .runtimeValue(recorder.createLazyBean()); }
The key points are:
So in summary, synthetic beans can be initialized lazily during RUNTIME_INIT for cases where eager STATIC_INIT instantiation is not needed. This allows optimizing startup time.
Use the Synthetic Bean: Now that your synthetic bean is registered, you can inject and use it in your 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(); } }
Running Your Application: Build and run your Quarkus application as usual, and the synthetic bean will be available for injection and use.
Synthetic beans in Quarkus provide a powerful mechanism for integrating external libraries, dynamically registering beans, and customizing bean behavior in your CDI-based applications. These beans, whose attributes are defined by extensions rather than Java classes, offer flexibility and versatility in managing dependencies.
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. Adoptez la puissance des haricots synthétiques dans Quarkus et faites passer votre injection de dépendance au niveau supérieur !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!