1. ホーム
  2. spring

[解決済み] Spring BeanPostProcessorは具体的にどのように動作するのですか?

2022-10-12 12:55:27

質問

Spring Coreの資格取得に向けて勉強しているのですが、Springがどのようにを処理するかについて疑問があります。 ビーンズライフサイクル をどのように扱うのか、特に ビーンポストプロセッサ .

というわけで、こんなスキーマができました。

その意味は私にとってかなり明確です。

次のような手順で ビーン定義の読み込み フェーズで行われます。

  • コンフィギュレーション クラスが処理され、かつ/または コンポーネント は がスキャンされ、かつ XML ファイル がパースされます。

  • BeanFactoryに追加されたBean定義(それぞれidでインデックス化されています。)

  • 特別な BeanFactoryPostProcessor ビーンが呼び出されると、任意のビーンの定義を変更することができます (たとえば、プロパティ・プレースホルダーの値の置換など)。

次に、以下の手順で ビーンズの作成フェーズ :

  • 各Beanはデフォルトでイーガーリーインスタンス化されます(依存関係が注入された状態で正しい順序で作成されます)。

  • 依存性注入の後、各Beanは後処理フェーズを通過します。 このフェーズでは、さらなる構成と初期化が行われる可能性があります。

  • 後処理の後、Beanは完全に初期化され、使用できるようになります(コンテキストが破棄されるまで、そのidによって追跡されます)。

OK、これは私にとってかなり明確です。 ビーンポストプロセッサには2つのタイプがあります。 であることも知っています。

  • イニシャライザーです。 指示があればビーンを初期化します(@PostConstructなど)。

  • そして 残りはすべて という追加設定を可能にするもので、その は初期化ステップの前でも後でも実行することができます。

そして、このスライドを投稿します。

というのは、私にとって非常に明確なことです。 初期化子 でアノテーションされたメソッドです。 ポストコンストラクト アノテーションがあり、セッターメソッドの直後(つまり依存性注入の後)に自動的に呼び出されるメソッドで、私はいくつかの初期化バッチを実行するために使用できることを知っています(前の例のようにキャッシュを移入するように)。

しかし、もう一つのビーンポストプロセッサは一体何を表しているのでしょうか?これらのステップが実行されると言ったとき、私たちは何を意味するのでしょうか。 初期化フェーズの前または後に実行される ?

私のBeanはインスタンス化され、依存関係が注入され、そして初期化フェーズが完了します。 ポストコンストラクト アノテーションされたメソッドの実行によって) 完了します。Bean Post Processorが初期化フェーズの前に使用されるというのはどういうことでしょうか。それは ポストコンストラクト アノテーションされたメソッドの実行の前に起こるということですか?依存性注入の前(セッターメソッドが呼ばれる前)に起こる可能性があるということでしょうか?

そして、それが実行されると言うとき、私たちは正確に何を意味するのでしょうか? 初期化ステップの後 . の実行の後に行われるということです。 @PostContruct アノテーションされたメソッドの実行後ということでしょうか?

が必要な理由は簡単に頭で理解できます。 ポストコンストラクト アノテーションされたメソッドが必要な理由は簡単に理解できますが、他の種類のビーンポストプロセッサの典型的な例を理解できません。

どのように解決するには?

Springのドキュメントでは、以下のBPPを説明しています。 BeanPostProcessorを使用したBeanのカスタマイズ . BPPビーンは、他のビーンより先に作成され、新しく作成されたビーンと相互作用する特別な種類のビーンです。この構成で、Springは、単に BeanPostProcessor を実装するだけで、ライフサイクルの動作にフックし、カスタマイズする手段を提供します。

のようなカスタムBPPを持つことは

public class CustomBeanPostProcessor implements BeanPostProcessor {

    public CustomBeanPostProcessor() {
        System.out.println("0. Spring calls constructor");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println(bean.getClass() + "  " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println(bean.getClass() + "  " + beanName);
        return bean;
    }
}

が呼び出され、作成されたすべてのビーンについてクラスとビーン名が出力されます。

メソッドがビーンのライフサイクルにどのように適合し、いつメソッドが呼び出されるかを理解するために、以下のサイトをチェックしてください。 ドキュメント

postProcessBeforeInitialization(Object bean, String beanName) 適用する このBeanPostProcessorを、与えられた新しいBeanインスタンスに適用します。 初期化コールバック(InitializingBeanのafterPropertiesSetのような) またはカスタムinit-methodのような)前に、この新しいBeanPostProcessorを適用します。

postProcessAfterInitialization(Object bean, String beanName) 適用する このBeanPostProcessorを与えられた新しいBeanインスタンスに適用します。 初期化コールバック(InitializingBeanのafterPropertiesSetのような)の後に、このBeanPostProcessorを与えられた新しいBeanインスタンスに適用します。 またはカスタムinit-methodのような)任意のビーン初期化コールバックの後に、このBeanPostProcessorを適用します。

また、重要なビットは

<ブロッククオート

ビーンにはすでにプロパティ値が入力されていることでしょう。

との関係に関わるものについては @PostConstruct を宣言するのに便利なアノテーションであることに注意してください。 postProcessAfterInitialization メソッドを宣言する便利な方法であり、Springがそれを認識するのは、あなたが CommonAnnotationBeanPostProcessor を指定するか <context:annotation-config /> をビーン設定ファイルで指定します。を指定するか、あるいは @PostConstruct メソッドの前か後に実行されるか。 postProcessAfterInitializationorder プロパティに依存します。

複数のBeanPostProcessorインスタンスを構成することができます。 を設定することで、これらのBeanPostProcessorが実行される順序を制御することができます。 を設定することで、これらのBeanPostProcessorの実行順序を制御できます。