「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > Quarkus での合成 Bean の探索。強力な拡張メカニズム

Quarkus での合成 Bean の探索。強力な拡張メカニズム

2024 年 9 月 2 日に公開
ブラウズ:529

Exploring Synthetic Beans in Quarkus. A Powerful Extension Mechanism

Quarkus の世界では、依存関係注入の領域は豊富で多用途であり、開発者に Bean を管理および制御するための多数のツールを提供します。そのようなツールの 1 つは、合成 Bean の概念です。合成 Bean は、Java クラス、メソッド、またはフィールドから派生したものではない属性を持つ Bean を登録できる強力な拡張メカニズムです。代わりに、合成 Bean のすべての属性は拡張子によって定義されます。

この記事では、Quarkus の合成 Bean の世界を深く掘り下げていきます。合成 Bean の必要性、その実用的なアプリケーション、Quarkus アプリケーションで合成 Bean を作成して使用する方法について探っていきます。

合成 Bean について理解する

Quarkus では、Bean はアプリケーションの構成要素であり、Contexts and dependency Injection (CDI) フレームワークによって管理されます。通常、CDI Bean は、@ApplicationScoped、@RequestScoped、または @Inject などのさまざまな CDI アノテーションが付けられた Java クラスです。これらの注釈
CDI が Bean のライフサイクルと注入を自動的に管理できるようにします。

ただし、状況によっては、従来の CDI モデルにうまく適合しない Bean を登録する必要がある場合があります。ここで合成豆が活躍します。合成 Bean は拡張機能によって作成され、その属性はこれらの拡張機能によって完全に定義されます。通常の CDI の世界では、AfterBeanDiscovery.addBean() メソッドと SyntheticComponents.addBean() メソッドを使用してこれを実現します。 Quarkus では、これは SyntheticBeanBuildItem.

を使用して実現されます。

合成豆が必要になるのはいつですか?

では、Quarkus で合成 Bean を使用する必要があるのはどのような場合でしょうか?合成 Bean は、次の場合に強力なツールとなります。

  1. サードパーティ ライブラリの統合: CDI アノテーションを持たないサードパーティ ライブラリを使用していますが、CDI ベースのアプリケーションに統合する必要があります。合成 Bean を使用すると、このギャップを埋めることができます。

  2. 動的 Bean 登録: 構成やその他の要因に応じて、実行時に Bean を動的に登録する必要があります。合成 Bean を使用すると、その場で Bean を作成して登録できる柔軟性が得られます。

  3. カスタマイズされた Bean 管理: 標準の CDI アノテーションでは実現できない、Bean のスコープと動作に対するきめ細かい制御が必要です。

  4. 特殊な Bean の実装: 従来の Java クラスやメソッドに対応しない固有の属性を持つ特殊な Bean を作成したいと考えています。

  5. テスト用の依存関係のモック化: 合成 Bean は、テスト目的で依存関係をモックアウトし、モック実装を挿入する便利な方法を提供します。

合成完了ビルド項目

SynthesisFinishedBuildItem は、CDI Bean の検出および登録プロセスが完了したことを示すために使用されます。これにより、拡張機能は、登録されている Bean と対話しても安全な時期を知ることができます。

例えば:

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

SyntheticBeansRuntimeInitBuildItem

SyntheticBeansRuntimeInitBuildItem は、すべての合成 Bean が初期化された後、実行時に呼び出されるコールバックを登録するために使用されます。これは、合成 Bean に関連する追加の初期化ロジックを実行する必要がある場合に役立ちます。

例えば:

@BuildStep
SyntheticBeansRuntimeInitBuildItem initSyntheticBeans(){

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

    }

SyntheticBeansRuntimeInitBuildItem に渡されるコールバックは、初期化されたすべての合成 Bean の ID を含む Set を受け取ります。

要約すると、SynthesisFinishedBuildItem は Bean の検出が完了したことを示し、SyntheticBeansRuntimeInitBuildItem は合成 Bean に応じてロジックを初期化できます。

SyntheticBeanBuildItem を使用した合成 Bean の作成

Quarkus では、SyntheticBeanBuildItem クラスのおかげで、合成 Bean の作成は簡単なプロセスです。合成 Bean を作成して使用する手順を見てみましょう:

  1. 合成 Bean クラスの作成: まず、合成 Bean クラスを定義します。このクラスは合成 Bean の基礎となります。
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. Quarkus 拡張機能の作成: 合成 Bean を登録するには、Quarkus 拡張機能を作成する必要があります。この拡張クラスは、SyntheticBeanBuildItem を使用して 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();
  }
}

SyntheticBeanBuildItem の .creator() メソッドは、実行時に合成 Bean のインスタンスを作成するバイトコードを生成するために使用されます。

.creator() に渡される引数は Consumer で、メソッド内で Java バイトコードを生成できます。

この例では:

  1. mc は MethodCreator インスタンスです
  2. mc.returnValue(new MySyntheticBean()) は、MySyntheticBean の新しいインスタンスを作成し、それをメソッドから返すためのバイトコードを生成します。

つまり、本質的には、次のようなメソッドを生成するように Quarkus に指示していることになります。

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

この生成されたメソッドは、注入または使用する必要があるときに MySyntheticBean をインスタンス化するために呼び出されます。

バイトコード生成が使用される理由は、合成 Bean が実際の Java クラス/メソッドに対応していないため、それらをインスタンス化するメソッドを明示的に生成する必要があるためです

SyntheticBeanBuildItem の出力は、ビルド時に記録されたバイトコードです。これにより、実行時のインスタンスの作成方法が制限されます。一般的なオプションは次のとおりです:

  1. .creator() 経由で直接バイトコードを生成
  2. BeanCreator サブクラスを使用する
  3. @Recorder メソッド経由でインスタンスを生成

レコーダーのアプローチ

@Record および .runtimeValue() アプローチは、Quarkus で合成 Bean のインスタンスを提供する代替方法です。

これにより、@Record(STATIC_INIT) アノテーションが付けられたレコーダー クラス メソッドを介して合成 Bean をインスタンス化できるようになります。

例えば:

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

ここで、.runtimeValue() は、Bean をインスタンス化するためにレコーダー メソッドを参照します。これにより、RuntimeValue を直接渡して合成 Bean インスタンスを提供できるようになります。

例えば:

@BuildStep 
SyntheticBeanBuildItem syntheticBean(){

    RuntimeValue bean= //...

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

    }

RuntimeValue は、レコーダー、サプライヤー、プロキシなどから取得される可能性があります。

要約すると:

  • @Record は RuntimeValue を生成する 1 つのアプローチです
  • .runtimeValue() は、SyntheticBeanBuildItem に RuntimeValue を設定します。

どちらもランタイム インスタンスを提供するという同じ目標を達成しますが、方法は少し異なります。

Quarkus で合成 Bean のランタイム インスタンスを提供する場合、バイトコードを直接生成するよりもより高度なアプローチとして、(@Record 経由で) レコーダーを使用することを検討します。
.creator() を使用するか、単純な RuntimeValues.

を指定します。

レコーダーの使用がより高度になる理由をいくつか示します:

  • さらなるカプセル化 - Bean をインスタンス化するロジックは、ビルド ステップに直接含まれるのではなく、別のレコーダー クラスに含まれます。これにより、ビルド ステップが無駄なく保たれます。
  • 再利用 - レコーダー メソッドは、作成者のロジックを書き換えるのではなく、複数の合成 Bean 間で再利用できます。
  • ランタイム データ - Recorder メソッドはランタイムに実行されるため、ランタイム リソース、構成、サービスなどを活用して Bean を構築できます。
  • 依存関係の注入 - Recorder メソッドは他のサービスを注入できます。
  • ライフ サイクル制御 - @Record(STATIC_INIT) または @Record(RUNTIME_INIT) の注釈が付けられた Recorder メソッドにより、Bean インスタンス化のライフ サイクルをより詳細に制御できます。
  • マネージド Bean - レコーダー内でインスタンス化された Bean 自体を CDI マネージド Bean にすることができます。

要約すると、レコーダー メソッドは、合成 Bean をインスタンス化するためのより多くのカプセル化、柔軟性、および実行時データとサービスへのアクセスを提供します。これらにより、直接バイトコード生成と比較して、より高度な Bean 生成ロジックが可能になります。

ただし、.creator() による直接バイトコード生成は、レコーダーが過剰になる可能性がある単純な場合には依然として役立ちます。しかし、合成豆のニーズが高まるにつれ、レコーダーはより強力になり、
高度なアプローチ。

デフォルトの STATIC_INIT フェーズではなく、RUNTIME_INIT フェーズ中に初期化されるように Quarkus の合成 Bean を設定することが可能です。

これが例です:

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

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

    }

重要なポイントは次のとおりです:

  • SyntheticBeanBuildItem で setRuntimeInit() を使用して、RUNTIME_INIT としてマークします
  • レコーダー メソッドには @Record(RUNTIME_INIT) の注釈を付ける必要があります
  • STATIC_INIT中はランタイム初期化合成Beanにアクセスできません

要約すると、積極的な STATIC_INIT インスタンス化が必要ない場合、合成 Bean は RUNTIME_INIT 中に遅延的に初期化できます。これにより、起動時間を最適化できます。

合成 Bean を使用する: 合成 Bean が登録されたので、それをアプリケーションに注入して使用できます。

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

アプリケーションの実行: いつものように Quarkus アプリケーションをビルドして実行すると、合成 Bean を注入して使用できるようになります。

結論

Quarkus の合成 Bean は、外部ライブラリの統合、Bean の動的登録、CDI ベースのアプリケーションでの Bean の動作のカスタマイズのための強力なメカニズムを提供します。これらの Bean は、属性が Java クラスではなく拡張機能によって定義されており、依存関係の管理に柔軟性と多用途性をもたらします。

この記事で説明したように、Quarkus での合成 Bean の作成と使用は簡単なプロセスです。 SyntheticBeanBuildItem と Quarkus 拡張機能を活用することで、従来の CDI と、より専門的または動的な Bean 登録要件との間のギャップをシームレスに埋めることができます。

進化し続ける Java フレームワークの状況において、Quarkus は合成 Bean などの革新的なソリューションを提供することで傑出し続けており、現代的で効率的かつ柔軟なアプリケーション開発にとって魅力的な選択肢となっています。 Quarkus の合成 Bean のパワーを活用して、依存関係の注入を次のレベルに引き上げましょう!

リリースステートメント この記事は次の場所に転載されています: https://dev.to/yanev/exploring-synthetic-beans-in-quarkus-a-powerful-extension-mechanism-fbd?1 侵害がある場合は、[email protected] までご連絡ください。それを削除するには
最新のチュートリアル もっと>
  • ハクトーバーフェストに貢献する新しい方法: フロントエンド AI で直接
    ハクトーバーフェストに貢献する新しい方法: フロントエンド AI で直接
    Hacktoberfest が帰ってきます。今年は開発者が参加できるエキサイティングな新しい方法をもたらします。 従来の GitHub プル リクエストの代わりに、Webcrumbs プラットフォーム上のフロントエンド AI を通じて直接テンプレートを作成して送信できるようになりました。 tools...
    プログラミング 2024 年 11 月 7 日に公開
  • 関数ポインタが括弧なしで使用されると、「cout」に「1」が出力されるのはなぜですか?
    関数ポインタが括弧なしで使用されると、「cout」に「1」が出力されるのはなぜですか?
    なぜ「関数を呼び出さずに関数を出力します (f() ではなく f;)。常に 1 を出力しますか?」この中でこのコードでは、括弧を使用せずに pr という名前の関数を「呼び出し」ようとします。ただし、これは実際には関数を呼び出しているわけではありません。代わりに、関数ポインタを cout 関数に渡しま...
    プログラミング 2024 年 11 月 7 日に公開
  • Web ページを高速化する
    Web ページを高速化する
    DOM とは何ですか?それは何を食べるのでしょうか? DOM (Document Object Model) は Web ページとその開発の基礎です。これは、HTML および XML ドキュメント用のプログラミング インターフェイスであり、ドキュメントの構造をツリー状のオブジェクト...
    プログラミング 2024 年 11 月 7 日に公開
  • JavaScript での require と import
    JavaScript での require と import
    コーディングを始めたとき、require() を使用してモジュールやインポートを使用して他のファイルをインポートするいくつかの js ファイルを見たことを覚えています。何が違うのか、なぜプロジェクト間で一貫性がないのかがよくわからず、いつも混乱していました。同じことを疑問に思っている場合は、読み続け...
    プログラミング 2024 年 11 月 7 日に公開
  • イメージを使用した Vite/React アプリケーションのデプロイ: 完全ガイド
    イメージを使用した Vite/React アプリケーションのデプロイ: 完全ガイド
    Vite/React アプリケーションを GitHub Pages にデプロイすることはエキサイティングなマイルストーンですが、このプロセスでは、特に画像やアセットを扱う場合、予期せぬ課題が発生することがあります。このブログ投稿では、初期導入から一般的な問題のトラブルシューティング、効果的な解決策の...
    プログラミング 2024 年 11 月 7 日に公開
  • React アプリで API 呼び出しを最適化した方法
    React アプリで API 呼び出しを最適化した方法
    React 開発者として、私たちは、複数の急速な状態変化を API と同期する必要があるシナリオによく直面します。小さな変更ごとに API 呼び出しを行うのは非効率的であり、クライアントとサーバーの両方に負担がかかる可能性があります。ここで、デバウンスと賢明な状態管理が機能します。この記事では、ペイ...
    プログラミング 2024 年 11 月 7 日に公開
  • さあ行こう!
    さあ行こう!
    GO を試す必要がある理由 Go は、高速かつ軽量で静的に型付けされたコンパイル言語で、効率的で信頼性の高いアプリケーションの構築に最適です。そのシンプルさとクリーンな構文により、特に初心者にとって、学習と使用が簡単になります。 Go の優れた機能には、ゴルーチンによる組み込み同時...
    プログラミング 2024 年 11 月 6 日に公開
  • PNG 画像を CSS データ URI の Base64 としてエンコードするにはどうすればよいですか?
    PNG 画像を CSS データ URI の Base64 としてエンコードするにはどうすればよいですか?
    CSS データ URI の PNG 画像に Base64 エンコーディングを使用するデータ URI を使用して PNG 画像を CSS スタイルシートに埋め込むには、PNG データ最初に Base64 形式にエンコードする必要があります。この手法を使用すると、外部画像ファイルをスタイルシート内に直接...
    プログラミング 2024 年 11 月 6 日に公開
  • API 時間別データの応答性の高い JavaScript カルーセル
    API 時間別データの応答性の高い JavaScript カルーセル
    I almost mistook an incomplete solution for a finished one and moved on to work on other parts of my weather app! While working on the carousel that w...
    プログラミング 2024 年 11 月 6 日に公開
  • Web 開発における PHP と JavaScript の主な違いは何ですか?
    Web 開発における PHP と JavaScript の主な違いは何ですか?
    PHP と JavaScript: サーバー側とクライアント側 PHP は JavaScript とは異なる役割を果たします。 PHPはサーバーサイドで動作します。サーバーはアプリケーションを実行します。フォームなどを処理します。フォームを送信すると、PHP がそれを処理します。一...
    プログラミング 2024 年 11 月 6 日に公開
  • C++ で構造体とクラスのメンバーを反復処理して、実行時に名前と値にアクセスするにはどうすればよいですか?
    C++ で構造体とクラスのメンバーを反復処理して、実行時に名前と値にアクセスするにはどうすればよいですか?
    構造体とクラスのメンバーの反復C では、構造体またはクラスのメンバーを反復して名前を取得することができます。そして価値観。これを実現するためのいくつかのアプローチを次に示します。マクロの使用REFLECTABLE マクロを使用して、イントロスペクションを可能にする構造体を定義できます。マクロは、構造...
    プログラミング 2024 年 11 月 6 日に公開
  • 項目 正確な答えが必要な場合は、float と double を避ける
    項目 正確な答えが必要な場合は、float と double を避ける
    float と double の問題: 科学的および数学的計算用に設計されており、2 進浮動小数点演算を実行します。 金銭の計算や正確な答えが必要な状況には適していません。 0.1 などの 10 の負の累乗を正確に表すことができないため、エラーが発生します。 例 1: ドル額を減算する際の計算が正し...
    プログラミング 2024 年 11 月 6 日に公開
  • Go で WebSocket を使用してリアルタイム通信を行う
    Go で WebSocket を使用してリアルタイム通信を行う
    チャット アプリケーション、ライブ通知、共同作業ツールなど、リアルタイムの更新が必要なアプリを構築するには、従来の HTTP よりも高速でインタラクティブな通信方法が必要です。そこで WebSocket が登場します。今日は、アプリケーションにリアルタイム機能を追加できるように、Go で WebSo...
    プログラミング 2024 年 11 月 6 日に公開
  • Python でプロキシを使用して Selenium Webdriver を実行する方法
    Python でプロキシを使用して Selenium Webdriver を実行する方法
    Python でプロキシを使用して Selenium Webdriver を実行するSelenium Webdriver スクリプトを Python スクリプトとしてエクスポートし、コマンド ラインから実行しようとすると、次のような問題が発生する場合があります。使用上の問題 プロキシの場合にエラーが...
    プログラミング 2024 年 11 月 6 日に公開
  • || がいつ行われるか演算子は JavaScript でデフォルトの演算子として機能しますか?
    || がいつ行われるか演算子は JavaScript でデフォルトの演算子として機能しますか?
    || の目的を理解するJavaScript の非ブール オペランドを持つ演算子JavaScript では、|| は演算子は論理 OR 演算子と呼ばれることが多く、通常はブール式を評価するために使用されます。ただし、 || が次のような場合に遭遇する可能性があります。演算子は非ブール値で使用されます...
    プログラミング 2024 年 11 月 6 日に公開

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3