Spring コンテナーの型

最終更新: 2023-12-14 04:20:44 +0800 +0800
原文は英語で書かれています。あなたはAI翻訳版を読んでいます。

Spring のコンテナー API には、Bean メタデータ、そのメタデータからオブジェクトを 作成するファクトリ、ファクトリとアプリケーションサービスを調整するアプリケーション コンテキストという 3 つの層があります。これらの層を分離すると、Spring のソース コードと拡張ポイントを理解しやすくなります。

Bean 定義とレジストリ #

BeanDefinition は 1 つの Bean の可変メタデータです。Bean クラスまたはクラス名、 スコープ、コンストラクター引数、プロパティ値、修飾子、ファクトリメソッド、 ライフサイクルメソッド、役割、ソース位置、明示的な依存関係を記録します。 親子メタデータ関係は Java 継承から独立しています。

一般的な実装は異なる登録経路に対応します。

  • RootBeanDefinition は Bean ファクトリが使用するマージ済み定義を表します。
  • ChildBeanDefinition は名前付き親定義からメタデータを継承します。
  • GenericBeanDefinition はマージ前に、スタンドアロンまたは親由来のメタデータを表現できます。
  • AnnotatedGenericBeanDefinition は登録されたクラスのアノテーションメタデータを公開します。
  • ScannedGenericBeanDefinition はコンポーネントクラスを先にロードせず、クラスパス スキャン時に読み取ったメタデータを公開します。

BeanDefinitionRegistry は Bean 名で定義を保存します。中心的な操作は定義の登録、 削除、問い合わせです。DefaultListableBeanFactory と GenericApplicationContext が 重要な実装です。

AnnotatedBeanDefinitionReader は明示的に指定されたコンポーネントクラスを登録します。

java
var context = new GenericApplicationContext();
var reader = new AnnotatedBeanDefinitionReader(context);
reader.register(OrderService.class);
context.refresh();

ClassPathBeanDefinitionScanner はパッケージから候補コンポーネントを検索し、その 定義を登録します。どちらの仕組みもアノテーションスコープ、命名、修飾子、条件、 BeanDefinitionCustomizer コールバックを適用します。カスタマイザーはレジストリ ポストプロセッサーを実装せず、登録時に対象を絞ったメタデータ変更を行えます。

BeanFactory、FactoryBean、ObjectFactory #

BeanFactory は実行時レジストリと依存関係解決 API です。定義を検索し、Bean を作成し、 協働オブジェクトを解決し、シングルトンの同一性を管理し、ライフサイクルプロセッサーを 適用します。ListableBeanFactory は列挙を追加し、HierarchicalBeanFactory は親検索 を追加し、ConfigurableListableBeanFactory はフレームワーク基盤へコンテナー設定を 公開します。アプリケーションコードはサービスロケーターとして getBean() を呼ぶ のではなく、ドメインの協働オブジェクトに依存します。

似た名前の 3 つの型には異なる責務があります。

  • BeanFactory はコンテナーです。
  • FactoryBean<T> は別のオブジェクトを作成する Bean です。名前を検索すると生成物が 返り、名前に & を付けるとファクトリ自体が返ります。getObjectType() と isSingleton() は生成物を説明します。
  • ObjectFactory<T> は getObject() を持つ最小のコールバックです。Spring は遅延取得 と内部作成コールバックに使用します。ObjectProvider<T> は任意、順序付き、ストリーム ベースのアクセスを加えます。

アプリケーションコンテキスト階層 #

ApplicationContext は ListableBeanFactory、 HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver, and related environment capabilities. ConfigurableApplicationContext は refresh()、close()、環境設定、設定可能な ファクトリへのアクセスなどのライフサイクル操作を追加します。

AbstractApplicationContext は refresh アルゴリズムを実装します。特殊化された基底 クラスが定義をファクトリへ届ける方法を決定します。

  • GenericApplicationContext は内部に 1 つの DefaultListableBeanFactory を所有します。 1 回の refresh() 呼び出し前に、そのレジストリ API で定義を登録できます。
  • AnnotationConfigApplicationContext は汎用コンテキストに AnnotatedBeanDefinitionReader と ClassPathBeanDefinitionScanner を組み合わせます。コンストラクターでクラスを 登録するかパッケージをスキャンし、その後 refresh できます。
  • Servlet 対応コンテキストは Web スコープと Servlet リソースを追加しますが、同じ コアファクトリ契約を維持します。

一部の古いコンテキスト実装は refresh 中に Bean ファクトリを再作成しますが、 GenericApplicationContext は refresh の繰り返しをサポートしません。フレームワークの 拡張は、すべてのコンテキストが複数回 refresh 可能だと仮定せず、具体的なコンテキスト のライフサイクルに従います。

refresh と生成される定義 #

アノテーション登録は、指定されたクラスの定義を最初に作成します。refresh 中に ConfigurationClassPostProcessor が @Configuration、コンポーネントスキャン、import、 @Bean メソッドを解析し、通常の Bean がインスタンス化される前に追加定義を登録します。 レジストリポストプロセッサーも同じ段階で定義を生成できます。Spring の AOT 処理は 事前に登録コードを生成できますが、結果の定義は同じ Bean ファクトリモデルへ渡されます。

ApplicationStartup はライフサイクルの意味を変えずに起動を計測します。 DefaultApplicationStartup は低オーバーヘッドの no-op 実装、BufferingApplicationStartup は上限付きステップデータを保持し、FlightRecorderApplicationStartup は Java Flight Recorder イベントを出力します。StartupStep には名前、タグ、明示的な終了があります。 起動計測はクリティカルパスで実行されるため、カスタム基盤はタグを低コストに保ちます。

拡張ポイントを選択する #

要件に合う最も狭い層を使用します。

  1. BeanDefinitionCustomizer で登録時に定義をカスタマイズする。
  2. BeanDefinitionRegistryPostProcessor または BeanFactoryPostProcessor でメタデータを追加・変換する。
  3. BeanPostProcessor でインスタンスをインターセプトする。
  4. FactoryBean でオブジェクトを生成する Bean を構築する。
  5. GenericApplicationContext またはアプリケーションコンテキストのサブタイプで完全な 調整コンテナーを構築する。

Primary References #

コメント

GitHub で閲覧・コメントする(投稿にはログインが必要です)