Beanの初期化が完了した後にメソッドを呼び出す方法は?


237

ApplicationContextのロード時に一度だけ(非静的)メソッドをBeanで呼び出す必要がある使用例があります。これにMethodInvokingFactoryBeanを使用しても大丈夫ですか?または、より良い解決策がありますか?

補足として、私はConfigContextLoaderListenerを使用してWebアプリケーションにアプリケーションコンテキストをロードします。そして、もしBean 'A'がインスタンス化されたら、methodA()を一度だけ呼び出してください。

これをどのようにうまく行うことができますか?

回答:


197

あなたは次のようなものを使うことができます:

<beans>
    <bean id="myBean" class="..." init-method="init"/>
</beans>

これにより、Beanがインスタンス化されるときに「init」メソッドが呼び出されます。


15
ただし、Spring Beanの初期化を台無しにしたくないので、ほとんどの場合、postConstructの方が優れています。
lwpro2 2013年

4
@ lwpro2ここで「Spring Beanの初期化を台無しにしたくない」とはどういう意味ですか?
Yngve Sneen Lindal 2014

@Mercer Traiesteここでクラス属性に何を与えるべきですか?ここでコントローラクラスを指定できますか?
KJEjava48 2016年

313

他の回答で@PostConstructの提案を拡張するには、これは本当に私の考えでは最良の解決策です。

  • Spring APIから分離されたコードを維持します(@PostConstructはjavax。*にあります)
  • Beanを初期化するために呼び出す必要があるものとして、initメソッドに明示的に注釈を付けます
  • Spring Beanの定義にinit-method属性を追加することを覚えておく必要はありません。Springは自動的にメソッドを呼び出します(とにかく、annotation-configオプションをコンテキストの他の場所に登録するとします)。

9
ありがとう、これでうまくいきます。Springで使用する場合は、「<context:annotation-config />」を含めて、CommonAnnotationBeanPostProcessor Beanを登録する必要があります(上記のとおり)
khylo

2
適切な方法<context:component-scan>も機能し、クラスパスにSpring以外の大きなライブラリがある場合に起動時間を短縮するのに役立ちます。
ドナルフェロー、

5
PostConstructのJavaDocは、唯一の方法は、クラスごとに、それに注釈を付けることができることを言う:docs.oracle.com/javaee/5/api/javax/annotation/...
アンドリュー・スワン

@PostConstructは、トランザクションマネージャとの仕事をしません、以下を参照してくださいforum.spring.io/forum/spring-projects/data/...
MMM

2
@PostConstructは、インスタンス化しているBeanが独自のクラスではなく、サードパーティのクラスである場合にもあまり役に立ちません
John Rix

102

リファレンスで説明されているように、考慮すべき3つの異なるアプローチがあります。

init-method属性を使用する

長所:

  • インターフェースを実装するためにBeanを必要としません。

短所:

  • Beanが正しく構成されていることを確認するために、構築後にこのメソッドを即座に示す必要はありません。

InitializingBeanを実装する

長所:

  • init-methodを指定したり、コンポーネントのスキャンや注釈処理を有効にする必要はありません。
  • ライブラリで提供されるBeanに適しています。このライブラリを使用するアプリケーションがBeanのライフサイクルに関与することを望まない場合。

短所:

  • init-methodアプローチよりも侵襲的です。

JSR-250 @PostConstructライフサイクルアノテーションを使用する

長所:

  • コンポーネントスキャンを使用してBeanを自動検出する場合に役立ちます。
  • 初期化に特定の方法が使用されることを明確にします。意図はコードに近いです。

短所:

  • 初期化は構成で集中的に指定されなくなりました。
  • アノテーション処理をオンにすることを忘れないでください(これは時々忘れられることがあります)

4
@PostConstruct初期化処理の最後にメソッドを呼び出す必要があるのはクラスの一部なので、実際に使用するのは良いことだと思います。
ドナルフェロー、

そのクラスが本当にそれを必要とし、コンストラクターでそれを行うことができない場合、私はそれをコードのにおいだと考えます。
user482745 2017年

39

実装してみましたInitializingBeanか?まさにあなたが求めているもののように聞こえます。

欠点は、BeanがSpring対応になることですが、ほとんどのアプリケーションではそれほど悪くありません。


2
XMLでinitメソッドを指定するよりも、インターフェイスの実装を選択する理由はありますか?
マーク・

4
それは好みの問題です。インターフェースはSpringコンポーネントモデルの一部であり、その目的だけを果たしますが、カスタムの名前付きメソッドの場合、コンポーネントのライフサイクルを完了するために呼び出す必要があるかどうかは明確ではありません。これは主にコミュニケーションに役立ちます。もちろん、Springフレームワークへの依存関係が導入されているという欠点があります。それは明確な意味を持っていますが、依存性を導入しないとの間での素敵な方法は...、@PostConstructの使用である
オリバーDrotbohm

7
Oliverは素晴らしい言い訳をくれますが、本当にinitメソッドについては忘れてしまいました:)もう1つの理由は、すべてのプロパティが設定された後、型自体が「終了」する必要があることをタイプ自体が知っていることです。基本的には、構成に含まれるべきものです。
Jon Skeet、

8

アプリケーションコンテキストにカスタムBeanPostProcessorをデプロイして、それを行うことができます。または、BeanにSpringインターフェースを実装してもかまわない場合は、InitializingBeanインターフェースまたは「init-method」ディレクティブ(同じリンク)を使用できます。


BeanPostProcessorの記述方法の詳細は誰にもありますか。それはまさに私が必要としているもののようです。乾杯:)
ピークの2009

Springには多くの例が付属しています。BeanPostProcessorのJavaDoc APIを見るだけで、多くの実装クラスへのリンクが見つかります。次に、それらのソースコードを確認します。
Rob H

-7

2つのアプローチ、つまり、

  1. @PostConstruct そして
  2. init-method="init"

個人的な経験から、(1)を使用するのはサーブレットコンテナでのみ機能するのに対し、(2)はデスクトップアプリケーションを含め、どの環境でも機能することに気付きました。したがって、スタンドアロンアプリケーションでSpringを使用する場合、(2)を使用して、「初期化後にこのメソッドを呼び出す」ことを実行する必要があります。


4
技術的には、@PostConstruct(Springベースのアプリで使用される場合)は、所有するSpringコンテキストの寿命に関連付けられます。このようなコンテキストは、あらゆる種類のアプリケーションで使用できます。
ドナルフェロー、

それは私が期待していた行動でしたが、うまくいきませんでした。
Ayorinde
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.