web-dev-qa-db-ja.com

Spring BeanPostProcessorはどのように機能しますか?

私はSpring Core認証のために勉強していますが、Springがどのようにbeansライフサイクルを処理し、特にbean post processorを処理するのか疑問があります。

だから私はこのスキーマを持っています:

enter image description here

私にとってそれが何を意味するかはかなり明確です:

Load Bean Definitionsフェーズでは、次の手順が実行されます。

  • @ Configurationクラスが処理され、および/または@ Componentsがスキャンされ、および/またはXMLファイルが解析されます。

  • BeanFactoryに追加されたBean定義(それぞれがそのidの下でインデックス付けされます)

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

その後、beans creation phaseで次の手順が実行されます。

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

  • 依存性の注入後、各Beanは後処理フェーズを通過し、さらに構成および初期化が行われる場合があります。

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

わかりました、これは私にとってはかなり明確であり、2種類のBeanポストプロセッサがあるであることも知っています

  • Initializers:指示された場合、Beanを初期化します(@PostConstruct)。

  • およびその他すべて:追加の構成を可能にし、初期化ステップの前後に実行可能

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

enter image description here

したがって、initializers Beanポストプロセッサ(@ PostContructアノテーションが付けられたメソッドであり、setterメソッドの直後に自動的に呼び出されるメソッドは何であるかは非常に明確です依存性注入の後)、初期化バッチを実行するために使用できることを知っています(前の例のようにキャッシュにデータを追加します)。

しかし、他のBeanポストプロセッサを正確に表すものは何ですか?これらの手順が実行されると言うとき、私たちは何を意味しますか初期化フェーズの前後

したがって、私のBeanはインスタンス化され、その依存関係が注入されるため、初期化フェーズは完了します(@ PostContructアノテーション付きメソッドの実行により)。初期化フェーズの前にBean Post Processorが使用されていると言うことはどういう意味ですか? @ PostContructアノテーション付きメソッドの実行前に発生することを意味しますか?依存性注入の前(セッターメソッドが呼び出される前)に発生する可能性があるということですか?

そして、それが実行されたと言うとき、正確に何を意味するのか初期化ステップの後@ PostContructアノテーション付きメソッドの実行後に発生することを意味しますか?

@ PostContruct注釈付きメソッドが必要な理由を簡単に理解できますが、他の種類のBeanポストプロセッサの典型的な例を理解することはできません。中古?

77
AndreaNobili

Springのドキュメントでは、BPPについて BeanPostProcessorを使用したBeanのカスタマイズ で説明しています。 BPP Beanは、他のBeanの前に作成され、新しく作成されたBeanと対話する特別な種類のBeanです。このコンストラクトを使用すると、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;
    }
}

が呼び出され、作成されたすべてのBeanのクラスとBean名が出力されます。

メソッドがBeanのライフサイクルにどのように適合するか、およびメソッドの呼び出しが正確に行われたときに、 docs を確認します。

postProcessBeforeInitialization(Object bean、String beanName)Bean初期化コールバック(InitializingBeanのafterPropertiesSetまたはカスタムinitメソッドなど)の前に、このBeanPostProcessorを指定された新しいBeanインスタンスに適用します)。

postProcessAfterInitialization(Object bean、String beanName)Bean初期化コールバック(InitializingBeanのafterPropertiesSetまたはカスタムinit-methodなど)の後に、指定された新しいBeanインスタンスにこのBeanPostProcessorを適用します)。

重要なのは

Beanにはすでにプロパティ値が入力されています。

@PostConstructとの関係については、このアノテーションはpostProcessAfterInitializationメソッドを宣言する便利な方法であり、registerCommonAnnotationBeanPostProcessorで指定するか、<context:annotation-config /> Bean設定ファイル。 @PostConstructメソッドを他のpostProcessAfterInitializationの前または後に実行するかどうかは、orderプロパティに依存します

複数のBeanPostProcessorインスタンスを設定でき、orderプロパティを設定することにより、これらのBeanPostProcessorが実行される順序を制御できます。

38
Master Slave

Beanポストプロセッサの典型的な例は、プロキシインスタンスで元のBeanをラップする場合です。 @Transactional注釈を使用する場合。

Beanポストプロセッサには、Beanの元のインスタンスが渡され、ターゲットのメソッドを呼び出すことができますが、アプリケーションコンテキストでバインドされる実際のBeanインスタンスも返すようになります。つまり、実際に必要なオブジェクト。これが役立つ典型的なシナリオは、Beanポストプロセッサがプロキシインスタンスでターゲットをラップする場合です。アプリケーションコンテキストでバインドされたBeanでのすべての呼び出しはプロキシを通過し、プロキシはターゲットBeanでの呼び出しの前後に何らかのマジックを実行します。 AOPまたはトランザクション管理。

25
marthursson

違いは、BeanPostProcessorはコンテキストの初期化にフックし、定義されたすべてのBeanに対してpostProcessBeforeInitializationおよびpostProcessAfterInitializationを呼び出すことです。

ただし、@PostConstructは、コンストラクターまたはsetメソッドの後でBeanの作成をカスタマイズする特定のクラスにのみ使用されます。

3
Tam Le