„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > Erkundung synthetischer Bohnen in Quarkus. Ein leistungsstarker Erweiterungsmechanismus

Erkundung synthetischer Bohnen in Quarkus. Ein leistungsstarker Erweiterungsmechanismus

Veröffentlicht am 02.09.2024
Durchsuche:186

Exploring Synthetic Beans in Quarkus. A Powerful Extension Mechanism

In der Welt von Quarkus ist der Bereich der Abhängigkeitsinjektion umfangreich und vielseitig und bietet Entwicklern eine Vielzahl von Tools zur Verwaltung und Kontrolle von Beans. Ein solches Werkzeug ist das Konzept der synthetischen Bohnen. Synthetische Beans sind ein leistungsstarker Erweiterungsmechanismus, mit dem Sie Beans registrieren können, deren Attribute nicht von einer Java-Klasse, -Methode oder einem Java-Feld abgeleitet sind. Stattdessen werden alle Attribute einer synthetischen Bean durch eine Erweiterung definiert.

In diesem Artikel tauchen wir tief in die Welt der synthetischen Bohnen in Quarkus ein. Wir untersuchen den Bedarf an synthetischen Bohnen, ihre praktischen Anwendungen und wie Sie sie erstellen und in Ihren Quarkus-Anwendungen verwenden.

Synthetische Bohnen verstehen

In Quarkus sind Beans die Bausteine ​​Ihrer Anwendung, die vom Contexts and Dependency Injection (CDI)-Framework verwaltet werden. Typischerweise sind CDI-Beans Java-Klassen, die mit verschiedenen CDI-Annotationen wie @ApplicationScoped, @RequestScoped oder @Inject annotiert sind. Diese Anmerkungen
Ermöglichen Sie CDI, den Lebenszyklus und die Injektion von Bohnen automatisch zu verwalten.

Es gibt jedoch Situationen, in denen Sie möglicherweise eine Bean registrieren müssen, die nicht genau in das traditionelle CDI-Modell passt. Hier kommen synthetische Bohnen ins Spiel. Synthetische Beans werden durch Erweiterungen erstellt und ihre Attribute werden vollständig durch diese Erweiterungen definiert. In der Welt des regulären CDI würden Sie dies mit den Methoden AfterBeanDiscovery.addBean() und SyntheticComponents.addBean() erreichen. In Quarkus wird dies mit SyntheticBeanBuildItem erreicht.

Wann brauchen Sie synthetische Bohnen?

Wann müssen Sie also möglicherweise synthetische Bohnen in Quarkus verwenden? Synthetische Bohnen sind ein leistungsstarkes Werkzeug, wenn:

  1. Integration von Drittanbieter-Bibliotheken: Sie arbeiten mit einer Drittanbieter-Bibliothek, die keine CDI-Anmerkungen hat, aber in Ihre CDI-basierte Anwendung integriert werden muss. Mit synthetischen Bohnen können Sie diese Lücke schließen.

  2. Dynamische Bean-Registrierung: Sie müssen Beans zur Laufzeit dynamisch registrieren, abhängig von der Konfiguration oder anderen Faktoren. Synthetische Bohnen geben Ihnen die Flexibilität, Bohnen im Handumdrehen zu erstellen und zu registrieren.

  3. Benutzerdefiniertes Bean-Management: Sie benötigen eine differenzierte Kontrolle über den Umfang und das Verhalten eines Beans, die mit Standard-CDI-Annotationen nicht erreicht werden kann.

  4. Implementieren spezialisierter Beans: Sie möchten spezialisierte Beans mit eindeutigen Attributen erstellen, die nicht den herkömmlichen Java-Klassen oder -Methoden entsprechen.

  5. Verspotten von Abhängigkeiten zum Testen: Synthetische Beans bieten eine nützliche Möglichkeit, Abhängigkeiten zu verspotten und Scheinimplementierungen für Testzwecke einzufügen.

SynthesisFinishedBuildItem

Das SynthesisFinishedBuildItem wird verwendet, um anzuzeigen, dass der CDI-Bean-Erkennungs- und Registrierungsprozess abgeschlossen ist. Dadurch können Erweiterungen erkennen, wann die Interaktion mit den registrierten Beans sicher ist.

Zum Beispiel:

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

SyntheticBeansRuntimeInitBuildItem

Das SyntheticBeansRuntimeInitBuildItem wird verwendet, um einen Rückruf zu registrieren, der zur Laufzeit aufgerufen wird, nachdem alle synthetischen Beans initialisiert wurden. Dies ist nützlich, wenn Sie eine zusätzliche Initialisierungslogik mit synthetischen Beans durchführen müssen.

Zum Beispiel:

@BuildStep
SyntheticBeansRuntimeInitBuildItem initSyntheticBeans(){

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

    }

Der an SyntheticBeansRuntimeInitBuildItem übergebene Rückruf erhält einen Set mit den IDs aller initialisierten synthetischen Beans.

Zusammenfassend zeigt SynthesisFinishedBuildItem an, dass die Bean-Erkennung abgeschlossen ist, während SyntheticBeansRuntimeInitBuildItem die Initialisierung der Logik abhängig von synthetischen Beans ermöglicht.

Erstellen synthetischer Beans mit SyntheticBeanBuildItem

In Quarkus ist das Erstellen synthetischer Beans dank der SyntheticBeanBuildItem-Klasse ein unkomplizierter Prozess. Gehen wir die Schritte zum Erstellen und Verwenden einer synthetischen Bohne durch:

  1. Erstellen Sie die synthetische Bean-Klasse: Beginnen Sie mit der Definition der synthetischen Bean-Klasse. Dieser Kurs bildet die Grundlage für Ihre synthetische Bohne.
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. Erstellen Sie eine Quarkus-Erweiterung: Sie müssen eine Quarkus-Erweiterung erstellen, um Ihre synthetische Bean zu registrieren. Diese Erweiterungsklasse verwendet SyntheticBeanBuildItem, um Ihr Bean zu konfigurieren.

Ansatz zur Bytecode-Generierung

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();
  }
}

Die .creator()-Methode auf SyntheticBeanBuildItem wird verwendet, um den Bytecode zu generieren, der zur Laufzeit Instanzen der synthetischen Bean erstellt.

Das an .creator() übergebene Argument ist ein Consumer, der die Generierung von Java-Bytecode innerhalb einer Methode ermöglicht.

In diesem Beispiel:

  1. mc ist die MethodCreator-Instanz
  2. mc.returnValue(new MySyntheticBean()) generiert den Bytecode, um eine neue Instanz von MySyntheticBean zu erstellen und diese von der Methode zurückzugeben.

Im Wesentlichen weisen wir Quarkus also an, eine Methode zu generieren, die etwa so aussieht:

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

Diese generierte Methode wird dann aufgerufen, um die MySyntheticBean zu instanziieren, wenn sie injiziert oder verwendet werden muss.

Der Grund für die Verwendung der Bytecode-Generierung besteht darin, dass synthetische Beans nicht echten Java-Klassen/-Methoden entsprechen. Daher müssen wir explizit eine Methode generieren, um sie zu instanziieren.

Die Ausgabe von SyntheticBeanBuildItem ist Bytecode, der zur Erstellungszeit aufgezeichnet wird. Dies schränkt die Art und Weise ein, wie Instanzen zur Laufzeit erstellt werden. Gängige Optionen sind:

  1. Bytecode direkt über .creator() generieren
  2. Eine BeanCreator-Unterklasse verwenden
  3. Instanz über die @Recorder-Methode erzeugen

Recorder-Ansatz

Die @Record- und .runtimeValue()-Ansätze sind alternative Möglichkeiten, Instanzen für synthetische Beans in Quarkus bereitzustellen.

Dadurch können Sie die synthetische Bean über eine mit @Record(STATIC_INIT) annotierte Recorder-Klassenmethode instanziieren.

Zum Beispiel:

@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());
  }

Hier referenziert .runtimeValue() die Recorder-Methode, um die Bean zu instanziieren. Dies ermöglicht die direkte Übergabe eines RuntimeValue zur Bereitstellung der synthetischen Bean-Instanz.

Zum Beispiel:

@BuildStep 
SyntheticBeanBuildItem syntheticBean(){

    RuntimeValue bean= //...

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

    }

Der RuntimeValue könnte von einem Rekorder, Lieferanten, Proxy usw. stammen.

Also zusammenfassend:

  • @Record ist ein Ansatz zum Generieren des RuntimeValue
  • .runtimeValue() legt den RuntimeValue für das SyntheticBeanBuildItem fest

Beide erreichen das gleiche Ziel, eine Laufzeitinstanz bereitzustellen, nur auf leicht unterschiedliche Weise.

Wenn es um die Bereitstellung von Laufzeitinstanzen für synthetische Beans in Quarkus geht, würde ich die Verwendung von Rekordern (über @Record) als einen fortgeschritteneren Ansatz im Vergleich zur direkten Generierung von Bytecode in Betracht ziehen
mit .creator() oder Bereitstellung einfacher RuntimeValues.

Hier sind einige Gründe, warum die Verwendung von Rekordern fortgeschrittener sein kann:

  • Mehr Kapselung – Die Logik zum Instanziieren von Beans ist in einer separaten Recorder-Klasse enthalten und nicht direkt in Build-Schritten. Dadurch bleiben die Build-Schritte schlank.
  • Wiederverwendung – Recorder-Methoden können über mehrere synthetische Beans hinweg wiederverwendet werden, anstatt die Erstellerlogik neu zu schreiben.
  • Laufzeitdaten – Recorder-Methoden werden zur Laufzeit ausgeführt, sodass sie Laufzeitressourcen, Konfigurationen, Dienste usw. nutzen können, um Beans zu erstellen.
  • Abhängigkeitsinjektion – Recorder-Methoden können andere Dienste injizieren.
  • Lebenszykluskontrolle – Mit @Record(STATIC_INIT) oder @Record(RUNTIME_INIT) annotierte Recorder-Methoden bieten mehr Kontrolle über den Lebenszyklus der Bean-Instanziierung.
  • Verwaltete Beans – Beans, die in Rekordern instanziiert werden, können selbst CDI-verwaltete Beans sein.

Zusammenfassend lässt sich sagen, dass Recorder-Methoden mehr Kapselung, Flexibilität und Zugriff auf Laufzeitdaten und -dienste für die Instanziierung synthetischer Beans bieten. Sie ermöglichen eine fortschrittlichere Bean-Produktionslogik im Vergleich zur direkten Bytecode-Generierung.

Die direkte Bytecode-Generierung mit .creator() kann jedoch in einfachen Fällen nützlich sein, in denen Rekorder möglicherweise übertrieben sind. Da jedoch der Bedarf an synthetischen Bohnen wächst, sind Rekorder eine leistungsfähigere und
Fortgeschrittener Ansatz.

Es ist möglich, eine synthetische Bean in Quarkus so zu konfigurieren, dass sie während der RUNTIME_INIT-Phase anstelle der Standardphase STATIC_INIT initialisiert wird.

Hier ist ein Beispiel:

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

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

    }

Die wichtigsten Punkte sind:

  • Verwenden Sie setRuntimeInit() für das SyntheticBeanBuildItem, um es für RUNTIME_INIT zu markieren
  • Die Recorder-Methode muss mit @Record(RUNTIME_INIT) annotiert werden.
  • Auf die synthetischen Laufzeit-Init-Beans kann während STATIC_INIT nicht zugegriffen werden

Zusammenfassend lässt sich sagen, dass synthetische Beans während RUNTIME_INIT träge initialisiert werden können, wenn keine eifrige STATIC_INIT-Instanziierung erforderlich ist. Dies ermöglicht eine Optimierung der Startzeit.

Verwenden Sie die synthetische Bean: Nachdem Ihre synthetische Bean nun registriert ist, können Sie sie in Ihre Anwendung einfügen und verwenden.

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();
  }
}

Ausführen Ihrer Anwendung: Erstellen und führen Sie Ihre Quarkus-Anwendung wie gewohnt aus, und die synthetische Bean steht zur Injektion und Verwendung zur Verfügung.

Abschluss

Synthetische Beans in Quarkus bieten einen leistungsstarken Mechanismus zur Integration externer Bibliotheken, zur dynamischen Registrierung von Beans und zur Anpassung des Bean-Verhaltens in Ihren CDI-basierten Anwendungen. Diese Beans, deren Attribute durch Erweiterungen und nicht durch Java-Klassen definiert werden, bieten Flexibilität und Vielseitigkeit bei der Verwaltung von Abhängigkeiten.

Wie wir in diesem Artikel untersucht haben, ist die Erstellung und Verwendung synthetischer Bohnen in Quarkus ein unkomplizierter Prozess. Durch die Nutzung der Erweiterungen SyntheticBeanBuildItem und Quarkus können Sie die Lücke zwischen traditionellem CDI und spezielleren oder dynamischeren Bean-Registrierungsanforderungen nahtlos schließen.

In der sich ständig weiterentwickelnden Landschaft der Java-Frameworks sticht Quarkus weiterhin hervor, indem es innovative Lösungen wie synthetische Beans anbietet, was es zu einer überzeugenden Wahl für die moderne, effiziente und flexible Anwendungsentwicklung macht. Nutzen Sie die Kraft synthetischer Bohnen in Quarkus und bringen Sie Ihre Abhängigkeitsinjektion auf die nächste Stufe!

Freigabeerklärung Dieser Artikel ist abgedruckt unter: https://dev.to/yanev/exploring-synthetic-beans-in-quarkus-a-powerful-extension-mechanism-fbd?1 Bei Verstößen wenden Sie sich bitte an [email protected] um es zu löschen
Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3